I'm studying app development with swift and metal kit
I want to convert an int type array to Metalbuffer, because I have to cover that array data in Shader.h
Before operating the shader.h, the array's values have not problems.
But, in and after the shader.h, the buffer's that converted from array have some problems.
for example, I send [1, 2, 3, 4] to Metalbuffer and I call the renderEncoder.setVertexBuffer(Metalbuffer).
then, In the Shader.h it appears like [1, 0, 2, 0]
what's the problem???
this is my sample code
var int_array = Array(reapeating: 1, count: 100)
init(){
Buffers = MetalBuffer<Int>(device: device, array: int_array, index: kBuffers.rawValue, options: [])
}
func updateIntArray(){
for i in 0..<100 {
int_array[i] = i % 20
}
Buffers = MetalBuffer<Int>(device: device, array: int_array, index: kBuffers.rawValue, options: [])
(other codes about rendering)
renderEncoder.setVertexBuffer(Buffers)
}
the updateIntArray is called per every frame by view controller.
I printed the sizeof(Buffers[i]) after the shader call, it was 4!
How can I preserve the data without being inserted with 0?
Thank you!
There's a lot of code missing from your question, but I will show you how I pass an array as a parameter to my fragment shader.
I have a ShaderTypes.h file to create a custom value type that can be used with both Swift and MSL (Metal Shading Language). You will need a bridging header for this if you want to use it on the Swift side.
#ifndef ShaderTypes_h
#define ShaderTypes_h
#include <simd/simd.h>
typedef struct {
float intensity;
float time;
float width;
float height;
float originX;
float originY;
}KeyPointValues;
My goal is to pass an array of KeyPointValues as a parameter to my fragment shader. On the swift side I do something like this:
var keyPoints = [KeyPointValues()]
for index in 0...10 {
keyPoints.append(KeyPointValues())
}
var count = keyPoints.count
guard let keyPointBuffer = context.device.makeBuffer(bytes: keyPoints, length: MemoryLayout<KeyPointValues>.stride * count) else { return }
commandEncoder.setFragmentBuffer(keyPointBuffer, offset: 0, index: 0)
commandEncoder.setFragmentBytes(&count, length: MemoryLayout.size(ofValue: count), index: 1)
You need to pass in count as well because there is no keyPoints.count counterpart in MSL.
Then the fragment shader looks something like this:
#include <metal_stdlib>
#include <simd/simd.h>
#import "ShaderTypes.h"
using namespace metal;
fragment half4 rosyFilter(device const KeyPointValues *keyPoints [[buffer(0)]],
constant uint &count [[ buffer(1) ]]
) {
for(uint index = 0; index < count; index++) {
float intensity = keyPoints[index].intensity;
}
}
Hopefully this can get you started in the right direction. You are using an array of Int, so it should be easier as there is probably no need to define a custom struct to use between Swift and MSL.
I am also somewhat new to Metal so I'm not sure if this is the best way of doing things. I appreciate any feedback from people with more experience.
I am creating an array in TCL for which the input should be a series of numbers. The first
two elements of the array is supposed to carry the information for deletion of the elements present inside the array. First element must carry the index of the element
occupying the array where the deletion should start with and the second element
carry the index of the element occupying the array up to which the deletion should
progress.
I am kind of new to TCL and tried the below code but facing errors saying cant read array (numarray here). Some help in fixing it is most welcome.
#! /user/bin/tclsh
puts "Enter sequence count: ";
gets stdin count;
puts "\nEnter the numbers: ";
for {set i 0} {$i < $count} {incr i} {
gets stdin numarray($i);
}
set delstart $numarray(0);
puts "Starting index: " $numarray(0);
set delend $numarray(1);
for {set $i $delstart} {$i < $delend} {incr $i} {
unset numarray($i);
}
puts "\nNumber array after deletion :";
foreach $i [array names numarray] {
puts "$numarray($i)";
}
You have multiple problems throughout the code due to one underlying issue.
Generally speaking, when you want the value of a variable, use the $ in front.
When you are writing to a variable, use the variable name.
I will use one line from your code as an example:
for {set $i $delstart} {$i < $delend} {incr $i} {
As it is, the command would be interpreted as:
for {set 12 $delstart} {$i < $delend} {incr 12} {
12 is a valid variable name, but not the one you are using.
Should be:
for {set i $delstart} {$i < $delend} {incr i} {
Only the test $i < $delend needs the value.
I want to write three for loops with promises something like this:
for i = 1 .. 3
for j = 1 .. 5
for k = 1 .. 6
post call to db to check if there is item on location i, j, k
step 1: check 1,1,1
step 2: check 1,1,2 item is found or inc next index
...
I searched for similar questions but I get only one-dimensional array loops examples.
I found this very hard problem and I hope you guys can help me. Thanks.
piping promises can be done linearly. So in your case, you have to first generate an array which holds all possible combinaisons like so:
$locations = [
[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4],
....
];
Then you can easily loop over this array and pipe your promises. Hope this helps
You can't combine a synchronous for loop with asynchronous operations and get things to sequence properly because there's no way to make a for loop "wait" for a promise to finish. The for loop runs synchronously so it will just start all the async operations at once.
So, instead you have to do your iterations another way. If you were iterating just one parameter, there would be a number of ready-made ways to do that, but I'm not aware of any pre-built solutions for iterating three nested variables so you will have to build your own. Here's one way to do it. This method is custom coded for your iterations which makes it a bit less code that a general scheme:
// fn gets called like this fn(i, j, k) and must return a promise
function iterateLevels(fn) {
var i = 1, iMax = 3;
var j = 1, jMax = 5;
var k = 1, kMax = 6;
function next() {
if (k > kMax) {
j++;
k = 1;
}
if (j > jMax) {
i++;
j = 1;
}
if (i > iMax) {
return;
}
return fn(i, j, k).then(function(result) {
k++;
// process result here
// if you want to continue processing, then
return next();
});
}
return next();
}
Here's a working demo implementation using a promise with a random delay: https://jsfiddle.net/jfriend00/q2Lnhszt/
The next() function with the outer scope variables i, j and k is essentially a state machine where each time you call next() it runs the next iteration and updates its state.
This could be made generic so you pass in how many levels of iteration and what the start and stop values for each level are and you could pass in a function for processing the result. Making it generic adds more code to the implementation and makes the logic a little harder to follow.
Kotlin has very nice iterating functions, like forEach or repeat, but I am not able to make the break and continue operators work with them (both local and non-local):
repeat(5) {
break
}
(1..5).forEach {
continue#forEach
}
The goal is to mimic usual loops with the functional syntax as close as it might be. It was definitely possible in some older versions of Kotlin, but I struggle to reproduce the syntax.
The problem might be a bug with labels (M12), but I think that the first example should work anyway.
It seems to me that I've read somewhere about a special trick/annotation, but I could not find any reference on the subject. Might look like the following:
public inline fun repeat(times: Int, #loop body: (Int) -> Unit) {
for (index in 0..times - 1) {
body(index)
}
}
This will print 1 to 5. The return#forEach acts like the keyword continue in Java, which means in this case, it still executes every loop but skips to the next iteration if the value is greater than 5.
fun main(args: Array<String>) {
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
nums.forEach {
if (it > 5) return#forEach
println(it)
}
}
This will print 1 to 10 but skips 5.
fun main(args: Array<String>) {
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
nums.forEach {
if (it == 5) return#forEach
println(it)
}
}
This will print 1 to 4, and break when reaching 5.
fun main(args: Array<String>) {
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
run breaking# {
nums.forEach {
if (it == 5) return#breaking
println(it)
}
}
}
Link to code snippet from ashuges.
Edit:
According to Kotlin's documentation, it is possible to simulate continue using annotations.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit# {
if (it == 3) return#lit // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with explicit label")
}
If you want to simulate a break, just add a run block
fun foo() {
run lit# {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return#lit // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with explicit label")
}
}
Original Answer:
Since you supply a (Int) -> Unit, you can't break from it, since the compiler do not know that it is used in a loop.
You have few options:
Use a regular for loop:
for (index in 0 until times) {
// your code here
}
If the loop is the last code in the method
you can use return to get out of the method (or return value if it is not unit method).
Use a method
Create a custom repeat method method that returns Boolean for continuing.
public inline fun repeatUntil(times: Int, body: (Int) -> Boolean) {
for (index in 0 until times) {
if (!body(index)) break
}
}
A break can be achieved using:
//Will produce "12 done with nested loop"
//Using "run" and a tag will prevent the loop from running again.
//Using return#forEach if I>=3 may look simpler, but it will keep running the loop and checking if i>=3 for values >=3 which is a waste of time.
fun foo() {
run loop#{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return#loop // non-local return from the lambda passed to run
print(it)
}
}
print(" done with nested loop")
}
And a continue can be achieved with:
//Will produce: "1245 done with implicit label"
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return#forEach // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with implicit label")
}
As anyone here recommends... read the docs :P
https://kotlinlang.org/docs/reference/returns.html#return-at-labels
EDIT:
While the main question asks about forEach, it's important to consider the the good old "for". Using Kotlin doesn't mean we need to use forEach all the time. Using the good old "for" is perfectly ok, and sometimes even more expressive and concise than forEach:
fun foo() {
for(x in listOf(1, 2, 3, 4, 5){
if (x == 3) break //or continue
print(x)
}
print("done with the good old for")
}
As the Kotlin documentation says, using return is the way to go. Good thing about Kotlin is that if you have nested functions, you can use labels to explicitly write where your return is from:
Function Scope Return
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
/** Non-local return directly to the caller of foo(). */
if (it == 3) return
print(it)
}
println("this point is unreachable")
}
Local Return
It doesn't stop going through forEach loop (it's like a continue in for loop).
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit#{
/** Local return to the caller of the lambda, i.e. the forEach loop. */
if (it == 3) return#lit
print(it)
}
print(" done with explicit label")
}
Check out the documentation, it's really good :)
You can use return from lambda expression which mimics a continue or break depending on your usage.
This is covered in the related question: How do I do a "break" or "continue" when in a functional loop within Kotlin?
continue type behaviour in forEach
list.forEach { item -> // here forEach give you data item and you can use it
if () {
// your code
return#forEach // Same as continue
}
// your code
}
for break type behaviour you have to use for in until or for in as per the list is Nullable or Non-Nullable
For Nullable list:
for (index in 0 until list.size) {
val item = list[index] // you can use data item now
if () {
// your code
break
}
// your code
}
For Non-Nullable list:
for (item in list) { // data item will available right away
if () {
// your code
break
}
// your code
}
I have the perfect solution for this (:
list.apply{ forEach{ item ->
if (willContinue(item)) return#forEach
if (willBreak(item)) return#apply
}}
Break statement for nested loops forEach():
listOf("a", "b", "c").forEach find#{ i ->
listOf("b", "d").forEach { j ->
if (i == j) return#find
println("i = $i, j = $j")
}
}
Result:
i = a, j = b
i = a, j = d
i = c, j = b
i = c, j = d
Continue statement with anonymous function:
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return
print("$value ")
})
Result:
1 2 4 5
Maybe change forEach to this:
for (it in myList) {
if (condition) {
doSomething()
} else {
break // or continue
}
}
It works for HashMap's:
for (it in myMap) {
val k = it.key
val v = it.value
if (condition) {
doSomething()
} else {
break // or continue
}
}
If the condition depends on the outcome of a previous element in the list, you can use sequence and takeWhile to execute depth-first lazily.
sequenceOf(1, 2, 3, 4, 5).map { i ->
println("i = ${i}")
i < 3
}.takeWhile { success ->
println("success = ${success}")
success
}.toList()
will print
i = 1
success = true
i = 2
success = true
i = 3
success = false
You need the terminal toList() in the end to execute the sequence.
More details: https://kotlinlang.org/docs/sequences.html#sequence
fun part2(ops: List<Int>): Int = ops.asSequence()
.scan(0) { acc, v -> acc + v }
.indexOf(-1)
If you can afford to turn a collection into a sequence, normally the cost is trivial, then you should be able to take advantage of the deferred feature.
You might already notice asSequence in the above. It's here for saving us going over the entire list. Right after we have a match via indexOf, it'll stop. Bingo! Saving us write a while here.
as in Part 2 of medium article.
I need to order an array of struct.
I've try:
let aRes = self.aSoundTracks_Filtered.sort{ $0.st < $1.st }
provide error: Cannot invoke 'sort' with an argument list of type '((_, _) -> _)'
also try this:
let hasPrefixAndSuffixw = self.aSoundTracks_Filtered.sort( $0.st < $1.st )
provide error: Anonymous closure argument not contained in a closure
Any idea? :)
My aSoundTracks_Filtered was delared like this:
var aSoundTracks_Filtered = [SoundTrack]()
My struct was like this:
struct SoundTrack {
let sID : Int
let st : String
}
Your code works fine when you tested in a Playground in the following way:
struct SoundTrack {
let sID : Int
let st : String
}
var aSoundTracks_Filtered = [SoundTrack]()
aSoundTracks_Filtered.append(SoundTrack(sID: 1, st: "a"))
aSoundTracks_Filtered.append(SoundTrack(sID: 2, st: "b"))
aSoundTracks_Filtered.sort{ $0.st > $1.st } // [{sID 2, st "b"}, {sID 1, st "a"}]
But sort() sorts an array in-place. What you probably want to use is sorted(), which does not modify the original array and returns a new sorted array:
let aRes = aSoundTracks_Filtered.sorted{ $0.st > $1.st }
The above code is for Swift 1.2, for Swift 2.0 returning a sorted array is called "sort" again, but it is a (protocol extension) method now instead of a global function. I hope this help you.
So, it's actually pretty simple. However I wonder where the selfcomes from when you access the array. I don't know which class it belongs to, in case it would belong to the struct itself (I wouldn't know why but just in case) you'll have to mark the function as mutating as you're changing the value of a struct's attribute. The second thing is actually that you'll have to use curley brackets:
self.aSoundTracks_Filtered.sort({$0.st < $1.st})