I am new to coding SML and am still trying to understand pattern matching. I am trying to find out how to access an argument from a function passed as an argument in SML. For example, if a function takes 2 arguments, a function and an integer, how can I access the argument (for simplicity, assuming it only has one) that the argument function has. Does this question even make sense in SML? Here is some code, which doesn't work, but I think it illustrates what I am trying to do.
fun argumentExtraction (n,f) =
case f of
fn x => x
A function doesn't have arguments, it takes arguments. You give arguments to the function and you get a result back. You can't ask the function what its arguments are because it doesn't have them yet. You are supposed to give the arguments to the function.
To make this perhaps a bit clearer, let us consider an example. Let's take the following functions:
fun add x y = x + y
fun plus1 x = x + 1
fun applyTwice f x = f (f x)
Now applyTwice takes a function and an argument and applies the function to the argument twice. We can call it like this:
applyTwice plus1 40
or like this:
applyTwice (add 1) 40
and in both cases the answer is going to be 42 (because that's the value of plus1 (plus1 40) and of add 1 (add 1 40), add 1 really being the exact same function as plus1).
Now I'm not sure whether you want to be able to pass (plus1 40) as the value for f and then somehow get 40 from that or whether you want to pass (add 1) and then somehow get back the 1, but both are impossible.
In the case of (plus1 40) you can't even pass that as the value for f. f is supposed to be a function, but (plus1 40) is an integer (41), not a function.
(add 1) on the other hand is a function and you can indeed pass it as the value for f. In fact I did so in my example. But what you can't do is get the value 1 back from it. I mean, imagine there was a way that you could do that. What should then happen if you passed plus1 instead of (add 1). What should you get back from that? There is no value captured in plus1, so there's really nothing to get back, but clearly plus1 is just as valid an argument to applyTwice as (add 1).
The only way this could possibly make sense is if partially applied function had a different type from normal functions, allowing you to define a function that accepts (add 1) as one argument, but not plus1. However that's not the case ML and there's really not much benefit to that. Having different types of functions would just make the type system more complicated and make it more difficult to define higher order functions (as they'd have to be able to deal with both types of function). Nor do I see the use case where this ability would even be helpful.
Related
Using the + function on a tuple of two Int64s returns the sum:
julia> +((1, 2))
3
However, using the + function on a variable that references a tuple gives the following error:
julia> a = (1, 2)
(1,2)
julia> +(a)
ERROR: MethodError: no method matching +(::Tuple{Int64, Int64})
I'm having trouble understanding why it behaves like this, especially when the following code returns true.
julia> typeof(a) == typeof((1, 2))
Note that, contrary to what you might think,
julia> :(+((1, 2)))
:(1 + 2)
This is a single function call equivalent to (+)(1, 2). There is no tuple, although the syntax may look like there is a tuple. (The + function, as you noted, does not work on tuples.) Is this behavior desirable? Well it was reported as a bug #12755, but then fixed. But the fix caused bug #12771 which resulted in the fix being reverted by pull #12772.
The solution to this mess is to avoid calling operators as functions without explicitly writing parentheses. That is, always write (+)(1, 2) instead of +(1, 2). You can verify that (+)((1, 2)) throws the error that you expect.
(This problem only occurs with unary operators, hence why | and * are not subject to it.)
If you're interested, the heart of this problem is a fundamental ambiguity between +(x, y) function call syntax and unary operator syntax. Here are a few situations that motivate parsing + and - as unary operators, even when followed by (:
In -(x+y)^2, it is highly likely that (-)((x+y)^2) was meant, not ((-)(x+y))^2. So we cannot simply unconditionally parse -( as a function call.
Instead what must be done is the thing after - parsed up to a certain precedence, so that -x * y is parsed as (-x) * y, -x + y as (-x) + y, but -x^y as -(x^y).
Exception: But this would make -(1, 2) parse as (-)((1, 2)), that is, a function called on a tuple. For whatever reason or another, it was decided to add an exception for when the thing after - looks like a function call tuple. This is so that +(1, 2) would work, but this is really mostly just a hack.
But from the parser's perspective, ((1, 2)) looks exactly like (1, 2); just the former is wrapped in parentheses.
My personal opinion is that the -(1, 2) notation is silly (and doesn't work in all cases anyway; e.g. in -(1, 2)^2). If that exception weren't around, and -(1, 2) consistently parsed as a unary function call on a tuple, then more consistency could be had without (I think) much loss. It's not too bad to just write 1 - 2 or (-)(1, 2) when a binary function call is desired.
I created a function which gets two string parameters. The function simply adds each string length. below is a code.
(defun add_twostring_length (mystr1 mystr2)
(+ (length mystr1) (length mystr2))
)
When I call add_twostring_length function like this,
(add_twostring_length "cpp" "lisp")
output is correct. 7
But, when I call the same function in the manner of using comma,
(add_twostring_length "cpp", "lisp")
I got an error message.
Error: Comma not inside a backquote.
[condition type: READER-ERROR]
I want to call function in the manner of (add_twostring_length "cpp", "lisp").
What is the wrong with the code?
picture showing error message
You might as well ask "why can't I call the function without parentheses?" In lisp, you call functions as an sexpr with the function in the car and the arguments in the cdr. There are no commas involved -- that's the syntax of lisp.
What you want is possible, but I will strongly advice against using it:
(set-macro-character #\,
#'(lambda (stream char)
(read stream t nil t)))
The above code creates the so called "read macro". At read-time common lisp will find all occurrences of , and ignore them. This makes possible calling functions like so:
(+ 1, 2, 3) ; => 6
However this will break escaping in templates:
`(1 2 ,(+ 3 4)) ; => (1 2 (+ 3 4))
Perhaps it is possible to make the read macro more intelligent, but I don't want to delve deeper into this, because I don't like the idea. Sorry.
The matrix-qr function in Racket's math library outputs two values. I know about call-with-values to put both output values into the next function you want.
However, how can I take each individual output and put define some constant with that value? The QR function outputs a Q matrix and an R matrix. I need something like:
(define Q ...)
(define R ...)
Also, how could I just use one of the outputs from a function that outputs two values?
The usual way to create definitions for multiple values is to use define-values, which pretty much works like you’d expect.
(define-values (Q R) ; Q and R are defined
(matrix-qr (matrix [[12 -51 4]
[ 6 167 -68]
[-4 24 -41]])))
There is also a let equivalent for multiple values, called let-values (as well as let*-values and letrec-values).
Ignoring values is harder. There is no function like (first-value ...), for example, because ordinary function application does not produce a continuation that can accept multiple values. However, you can use something like match-define-values along with the _ “hole marker” to ignore values and simply not bind them.
(match-define-values (Q _) ; only Q is defined
(matrix-qr (matrix [[12 -51 4]
[ 6 167 -68]
[-4 24 -41]])))
It is theoretically possible to create a macro that could either convert multiple values to a list or simply only use a particular value, but in general this is avoided. Returning multiple values should not be done lightly, which is why, for almost all functions that return them, it wouldn’t usually make much sense to use one of the values but ignore the other.
What could be the possible function foo, which has a type
’a * ’a -> int
in ML. i.e. a function which has the following type of the output
This seems to be homework, so I give you a partial solution and some hints only. The type you want is a 'a * 'a -> int, so the skeleton of a suitable function could be something like this (I assume you are using Standard ML):
fun foo(x, y) = ???
The ??? needs to meet two requirements: it must contain an expression that forces x and y to have the same type, and it must return an integer. The latter shouldn't be hard. For the former, there are many possibilities in SML, e.g., putting them in the same list, or returning them from the branches of the same if or case or handle.
I would like to pass the parameter values in meters or kilometers (both possible) and get the result in meters/second.
I've tried to do this in the following example:
u = 3.986*10^14 Meter^3/Second^2;
v[r_, a_] := Sqrt[u (2/r - 1/a)];
Convert[r, Meter];
Convert[a, Meter];
If I try to use the defined function and conversion:
a = 24503 Kilo Meter;
s = 10198.5 Meter/Second;
r = 6620 Kilo Meter;
Solve[v[r, x] == s, x]
The function returns the following:
{x -> (3310. Kilo Meter^3)/(Meter^2 - 0.000863701 Kilo Meter^2)}
which is not the user-friendly format.
Anyway I would like to define a and r in meters or kilometers and get the result s in meters/second (Meter/Second).
I would be very thankful if anyone of you could correct the given function definition and other statements in order to get the wanted result.
Here's one way of doing it, where you use the fact that Solve returns a list of rules to substitute a value for x into v[r, x], and then use Convert, which will do the necessary simplification of the resulting algebraic expression as well:
With[{rule = First#Solve[v[r,x]==s,x]
(* Solve always returns a list of rules, because algebraic
equations may have multiple solutions. *)},
Convert[v[r,x] /. rule, Meter/Second]]
This will return (10198.5 Meter)/Second as your answer.
You just need to tell Mathematica to simplify the expression assuming that the units are "possitive", which is the reason why it doesn't do the simplifications itself. So, something like
SimplifyWithUnits[blabla_, unit_List]:= Simplify[blalba, (#>0)&/#unit];
So if you get that ugly thing, you then just type %~SimplifyWithUnits~{Meter} or whatever.