Forwarding of variadic arguments

Swift does not have array splatting, which would be a nice way to forward variadic arguments to a function. Splatting has been suggested many times, but it has not become a part of the language. In Xcode you can do the following (well, could, if it had Island RTL Strings):

extension String {
    convenience init(format: String, arguments argList: Any...) {  // String is struct, so it should not be marked 'convenience' in Xcode
        let formatter = unsafeBitCast(String.Format(format:arguments:), to: ((String, [Any]) -> String).self)
        self.init(formatter(format, argList) as Object)  // 'as Object' is for Silver
    }
}

However, Silver does not have unsafeBitCast, and I don’t know whether the signatures are the same either. Is there a convenient way to do this in Silver?

Did they change the rules on this again?

what’s this supposed to do?

I’m not sure how it was before, but Xcode 12.1 says “Delegating initializers in structs are not marked with ‘convenience’” here.

Since ((String, Any...) -> String) and ((String, [Any]) -> String) are layout-compatible, unsafeBitCast can be used to rewrite the signature. This way we can pass an array to a function that expects a variadic parameter, which would be passed as an array anyhow. (The .self is needed to reference the type object.)

Ok, so structs don’t use convenience at all anyone, on ly classes? (rhetorical side question: whom the hell “designs” this language? it’s getting more insane by the day).

Let me know, and I’ll log an issue to adjust accordingly.

Curious; id expect those to be compatible without any cast at all. since its essentially the same ting, the ... is just syntactic sugar. Does it work w/o cast?

That’s true. It seems that convenience has never been necessary in structs, since they don’t have inheritance. (Actually it does not seem to be necessary in Silver either.) I don’t know if it has always been an error, though. The first Google hits with the error message seem to be from 2017.

There seems to be something funny going on with String.Format (it just returns the format string without the arguments), so I can’t test right now. However, wouldn’t the array get wrapped into another array? How would the compiler know whether the array was supposed to be splatted or passed as the only argument?

AlSo Silver allows convenience in structs, but doesn’t need it, Xcode doesn’t allow it? id say we keep it as is thgen, as Silver is more flexible (and allows symmetry between struct and class), and its easy to just mot use the keyword iff (a) so desired or (b) Xcode compatibility is needed?

Java, and a build prior to 2563, by any chance? If so, thats a known issue and should be fixed in latest…

IO dont see why. X... really just means “same x[] but let the caller omit the angle brackets”.

Yes, using convenience in struct is an error in Xcode. Leaving Silver as it is sounds fine.

WebAssembly and 2565

Let’s say I have f(_ argList: Any...) and I call it as f(["one", "two"], 2). In this case argList would be [["one", "two"], 2]. If I call it as f(["one", "two"]) instead, how will the compiler know whether I wanted argList to be [["one", "two"]] or ["one", "two"]?

Curious. might be related issue. Any chance you could put together a simple test case for me so I can log this? thanx!

This is a bit above my pay grade, but I don’t believe it would, no. That may well be a bug/incompatibility but AFAIK right now ... in Silver works same as param in Oxygene: it literally just means if you dont explicitly pass an array on the calling side, the compiler well pack it up for you. But you can still pass an array explicitly.

If you believe this behaving wrongly, I’d appreciate of you could create a small testcase (ideally not wasm, but .NET or Cocoa) that shows the wring behavior, and I can log an issue for the compiler team to review this.

@ck?

Sorry, my bad: I tried to use a C-style format string instead of .NET style. :man_facepalming: Turns out String.Format is not what I want. However, now that I was able to test with it, String.Format("{0}", 1) and String.Format("{0}", [1]) are indeed identical.

This would actually be good news for me, since it would make forwarding variadic arguments extremely easy. It would not be in line with Swift specification, though. In Swift, the variadic arguments are always packed in a list. This is what makes the forwarding difficult. I can make a test case later, but at the moment I am just happy that Silver is not compliant in this regard.

phew :wink:

Cool!

:wink:

I wont wake sleeping dogs, so lets just leave it as is until someone else complains…