Tuple to function arguments in Nim - tuples

Can I convert a tuple into a list of function arguments in Nim? In other languages this is known as "splat" or "apply".
For example:
proc foo(x: int, y: int) = echo("Yes you can!")
type:
Point = tuple[x, y: int]
let p: Point = (1,1)
# How to call foo with arguments list p?

I haven't seen this in the stdlib or any other lib, but you can certainly do it yourself with a macro:
import macros
macro apply(f, t: typed): typed =
var args = newSeq[NimNode]()
let ty = getTypeImpl(t)
assert(ty.typeKind == ntyTuple)
for child in ty:
expectKind(child, nnkIdentDefs)
args.add(newDotExpr(t, child[0]))
result = newCall(f, args)
proc foo(x: int, y: int) = echo("Yes you can!")
type Point = tuple[x, y: int]
let p: Point = (1,1)
# How to call foo with arguments list p?
apply(foo, p) # or:
foo.apply(p)
Further testing would be required to make sure this works with nested tuples, objects etc. You also might want to store the parameter in a temporary variable to prevent side effects from calling it multiple times to get each tuple member.

Hi I'm a bit late here but you can use function overloading
proc foo(x: int, y: int)
proc foo(point: Point)

Related

I got some trouble with ocaml polymorphic function

i need your help please, where is the error in my code ?
let create = Array.make_matrix 10 10;;
let assoc int = create int,create (char_of_int int);;
the error is
3 | let assoc int = create int,create (char_of_int int);;
^^^^^^^^^^^^^^^^^
Error: This expression has type char but an expression was expected of type
int
when you define a polymorphic function implicitly on Ocaml, it has a `weak type meaning that a type will be definitely assigned to the function after you've called it once, so because you called to create on an int, it now has a type int -> int array and won't accept a char as an argument.
This is the "value restriction". You can make it work by defining create like this:
let create v = Array.make_matrix 10 10 v
It works like this:
# let create v = Array.make_matrix 10 10 v;;
val create : 'a -> 'a array array = <fun>
# let assoc int = create int,create (char_of_int int);;
val assoc : int -> int array array * char array array = <fun>
The value restriction states that only "values" (in a certain sense) can be polymorphic; in particular, an expression that just applies a function can't be fully polymorphic. You define create by just applying a function to some values, so the value restriction prevents it from being polymorphic. The above definition defines create instead as a lambda (a fun in OCaml), which is a "value" per the value restriction. So it can be fully polymorphic.
You can read about the value restriction in Chapter 5 of the OCaml manual.

Is there an F# cast function with type inference like Seq.cast?

So I have some COM-types with hard-to-remember, long, unwieldy names, so I'd rather not have to type them out when casting from object if I can avoid it. With Seq.cast it'll infer the required type and cast as necessary.
Here's a simplified version with int instead:
> let o = 1 :> obj;;
val o : obj = 1
> let inc x = x+1;;
val inc : int -> int
> inc o;;
inc o;;
----^
stdin(15,5): error FS0001: This expression was expected to have type
int
but here has type
obj
Okay, makes sense. So we cast it:
> inc (o :?> int);;
val it : int = 2
However, if I cast it with Seq.cast I wouldn't need to explicitly write the type:
> inc ([o] |> Seq.cast |> Seq.head);;
val it : int = 2
Is there a function that works like cast below?
> inc (o |> cast);;
val it : int = 2
Is there an F# cast function with type inference like Seq.cast?
You can use the 'unbox' and 'box' operators to take advantage of type inference
inc (unbox o)
As Leaf mentioned, box and unbox work for conversions to/from obj. For other types you can use the upcast or static cast operators (:>) for upcasting and the downcast or dynamic cast (:?>) operators for downcasting. A wildcard can be used in place of an explicit type, for example: x :?> _.

defining a simple implicit Arbitary

I have a type Foo with a constructor that takes an Int. How do I define an implicit Arbitrary for Foo to be used with scalacheck?
implicit def arbFoo: Arbitrary[Foo] = ???
I came up with the following solution, but it's a bit too "manual" and low-level for my taste:
val fooGen = for (i <- Gen.choose(Int.MinValue, Int.MaxValue)) yield new Foo(i)
implicit def arbFoo: Arbitrary[Foo] = Arbitrary(fooGen)
Ideally, I would want a higher-order function where I just have to plug in an Int => Foo function.
I managed to cut it down to:
implicit def arbFoo = Arbitrary(Gen.resultOf((i: Int) => new Foo(i)))
But I still feel like there has got to be a slightly simpler way.
Well, you can use the underscore notation instead of defining the whole Foo-creating function as (i: Int) => new Foo(i)):
class Foo(i: Int)
(1 to 3).map(new Foo(_))
This works because Scala knows that Foo takes an Int, and that map is mapping over Ints, so there's no need to spell it all out explicitly.
So this is a bit shorter:
implicit def arbFoo = Arbitrary(Gen.resultOf(new Foo(_)))

WHILE loop for the LIST

I need to write a very simple function in SML. It should check if the value 'elem' is greater than any value of the field 'f1' in the list 'L'. The list 'L' contains 3 fields - 'f1','f2','f3'. The function should return 1 if the statement 'elem>f1' is true for any of the members of the list 'L'. Otherwise, the function should return 0. For instance:
L =
f1 f2 f3
1 4 6
2 1 2
3 4 8
8 5 9
elem = 3
fun check(L: myList, elem: int): int =
let
val counter = ref 0
val counter_end = length L
in
while (!counter <= counter_end) do
let val f1 = List.nth(L,counter)
in
if elem > f1 then 1 else 0
end
counter := !counter + 1
end
I don't know how to get the field 'f1' from the list 'L'. Any ideas are HIGHLY appreciated.
In SML (and functional languages in general), you'll typically want to rely on recursion rather than imperative constructs like loops.
I'm a bit rusty in SML, but here's one way to define the function
fun check elem [] = 0
| check elem ((f1,f2,f3)::tl) = if elem > f1 then 1 else check elem tl;
It can then be called like this:
(* define a list to scan *)
val L = [(1,4,6),(2,1,2),(3,4,8),(8,5,9)];
(* call the function on our list *)
check 3 L;
The function is defined recursively, using pattern matching: The first line says that if the function is called on an empty list, the result is zero.
The second line says that if it is called on a list, where the first element is the tuple (f1,f2,f3), then the result is 1 if elem > f1, and otherwise, it's the result of invoking the function recursively on the tail of the list
Also note that I omitted the type specifiers. You rarely need them, because the language infers the types automatically. The compiler already knows which types can be safely used with the code you wrote, so why bother telling it what types you think the arguments are going to be?
Use a recursive function instead of using a loop. (And it would probably make more sense to use a boolean return instead of an integer.)
Easiest way to extract the fields is via pattern matching in the argument list. Assuming your three fields are in a tuple, something like this:
fun check((f1,f2,f3)::L: myList, elem: int)

Type parameterization in Scala

So I'm learning Scala at the moment, and I'm trying to create an abstract vector class with a vector-space of 3 (x,y,z coordinates). I'm trying to add two of these vectors together with the following code:
package math
class Vector3[T](ax:T,ay:T,az:T) {
def x = ax
def y = ay
def z = az
override def toString = "&lt"+x+", "+y+", "+z+"&gt"
def add(that: Vector3[T]) = new Vector3(x+that.x, y+that.y, z+that.z)
}
The problem is I keep getting this error:
error: type mismatch; found :
T required: String def
add(that: Vector3[T]) = new
Vector3(x+that.x, y+that.y,
z+that.z)
I've tried commenting out the "toString" method above, but that doesn't seem to have any effect. Can anyone tell me what I'm doing wrong?
Using Scala 2.8, you could write:
case class Vector3[T: Numeric](val x: T, val y: T, val z: T) {
override def toString = "(%s, %s, %s)" format (x, y, z)
def add(that: Vector3[T]) = new Vector3(
plus(x, that.x),
plus(y, that.y),
plus(z, that.z)
)
private def plus(x: T, y: T) = implicitly[Numeric[T]] plus (x, y)
}
Let me explain. First, T: Numeric is a context bound that implicitly provides a Numeric[T] instance to your class.
The Numeric[T] trait provides operations on numeric types,
trait Numeric[T] extends Ordering[T] {
def plus(x: T, y: T): T
def minus(x: T, y: T): T
def times(x: T, y: T): T
def negate(x: T): T
// other operations omitted
}
The expression implicitly[Numeric[T]] retrieves this implicit context such that you can perform the operations such as plus on your concrete arguments x, y and z, as illustrated in the private method above.
You can now construct and add different instantiations of Vector3 such as with Int's and Double's:
scala> Vector3(1,2,3) add Vector3(4,5,6)
res1: Vector3[Int] = (5, 7, 9)
scala> Vector3(1.1, 2.2, 3.3) add Vector3(4.4, 5.5, 6.6)
res2: Vector3[Double] = (5.5, 7.7, 9.899999999999999)
Side-note: It's possible to use implicit conversions to convert values to Numeric[T].Ops instances such that the following could be written instead:
def add(that: Vector3[T]) = new Vector3(x + that.x, y + that.y, z + that.z)
I've deliberately chosen not to use these implicit conversions since they (may) incur some performance penalty by creating temporary wrapper objects. Actual performance impact depends on the JVM (e.g., to which extent its supports escape analysis to avoid actual object allocation on heap). Using a context bound and implicitly avoids this potential overhead ... at the cost of some verbosity.
You have not constrained the type parameter T and so the compiler is falling back to the interpretation of + as String concatenation.
The problem is T. It's of type Any, but Any doesn't have a + operator. The error about String is a bit miss leading. So you're going to have to define the min bound to a type that does.
Both the answers from #sblundy and #Randall Schulz are correct, of course, but in case you need some more concrete advice about how to constrain T then how about:
class Vector3[T <% Double](ax:T,ay:T,az:T) {
...
}