Tell if number is odd or even with SML - recursion

This is the second SML program I have been working on. These functions are mutually recursive. If I call odd(1) I should get true and even(1) I should get false. These functions should work for all positive integers. However, when I run this program:
fun
odd (n) = if n=0 then false else even (n-1);
and
even (n) = if n=0 then true else odd (n-1);
I get:
[opening test.sml]
test.sml:2.35-2.39 Error: unbound variable or constructor: even
val it = () : unit
How can I fix this?

The problem is the semicolon (;) in the middle. Semicolons are allowed (optionally) at the end of a complete declaration, but right before and is not the end of a declaration!
So the compiler is blowing up on the invalid declaration fun odd (n) = if n=0 then false else even (n-1) that refers to undeclared even. If it were to proceed, it would next blow up on the illegal occurrence of and at the start of a declaration.
Note that there are only two situations where a semicolon is meaningful:
the notation (...A... ; ...B... ; ...C...) means "evaluate ...A..., ...B..., and ...C..., and return the result of ...C....
likewise the notation let ... in ...A... ; ...B... ; ...C... end, where the parentheses are optional because the in ... end does an adequate job bracketing their contents.
if you're using the interactive REPL (read-evaluate-print loop), a semicolon at the end of a top-level declaration means "OK, now actually go ahead and elaborate/evaluate/etc. everything so far".
Idiomatic Standard ML doesn't really use semicolons outside of the above situations; but it's OK to do so, as long as you don't start thinking in terms of procedural languages and expecting the semicolons to "terminate statements", or anything like that. There's obviously a relationship between the use of ; in Standard ML and the use of ; in languages such as C and its syntactic descendants, but it's not a direct one.

I'm sure there's a didactic point in making these functions recursive, but here's some shorter ones:
fun even x = x mod 2 = 0
val odd = not o even

Related

How to correctly do line continuation in Julia?

In fortran, we can simply use & to do line continuation.
But I wonder, in Julia, is there a safe way to do line continuation?
I heard that sometimes Julia cannot identify line continuation and it can cause bugs? Because after, Julia does not seem to have any symbol to do line continuation. Can Julia correctly recognize the line continuation?
Like I define the below function with long arguments,
function mean_covar_init(kmix::Int64,dim_p::Int64,weight::Array{Float64,1},sigma::Array{Float64,2},mu::Array{Float64,2})
return nothing
end
If I do things like
function mean_covar_init(kmix::Int64
,dim_p::Int64
,weight::Array{Float64,1}
,sigma::Array{Float64,2}
,mu::Array{Float64,2})
return nothing
end
Is it safe? Thank you very much!
If you do the thing like you have presented it is safe because Julia sees ( in the first line of code so it will look for a closing ).
However a problematic code would be:
f() = 1
+ 2
The reason is that the f() = 1 part is a valid and complete function definition. Therefore you need to make sure to signal Julia that the line is incomplete. The three most typical ways to do it are:
Move the + to the end of first line:
f() = 1 +
2
Use ( and ) as a wrapper:
f() = (1
+ 2)
Use begin and end:
f() = begin 1
+ 2 end
Let me give another example with macros, which do not require parenthesis or punctuation and therefore can be often tricky. Therefore the following:
#assert isodd(4) "What even are numbers?"
if rewritten as
#assert isodd(4)
"What even are numbers?"
does not produce what you expect, and you need to do e.g.:
#assert(isodd(4),
"What even are numbers?")

Julia: Even-number datatype for functions

I have about 50 functions which should consume only even positive numbers. Right now I am checking each time with an "if" whether the number put in is zero or not:
function grof(x::Int)
if (x % 2) == 0
println("good")
else
throw("x is not an even number!!!!!!!!!!!!! Stupid programmer!")
end
end
Ideally, I would like to have a datatype which produces this automatically, i.e.
function grof(x::EvenInt)
println("good")
end
However, I am not able to produce this datatype by my own since I am unable to understand the documentary. Thanks for your help!
Best, v.
I don't think creating a type is warranted in such a situation: I would simply #assert that the condition is verified at the beginning of the function(s). (Funnily enough, checking the whether a number is even is the example that was chosen in the documentation to illustrate the effect of #assert)
For example:
julia> function grof(x::Int)
#assert iseven(x) "Stupid programmer!"
println("good")
end
grof (generic function with 1 method)
julia> grof(2)
good
julia> grof(3)
ERROR: AssertionError: Stupid programmer!
Stacktrace:
[1] grof(::Int64) at ./REPL[5]:2
[2] top-level scope at REPL[7]:1
EDIT: If you really want to create a type enforcing such a constraint, it is possible. The way to do this would be to
create a type (possibly subtyping one of the Number abstract types; maybe Signed)
define an inner constructor ensuring that such a type cannot hold an odd value
A very simple example to build upon would be along the lines of:
# A wrapper around an even integer value
struct EvenInt
val :: Int
# inner constructor
function EvenInt(val)
#assert iseven(val)
new(val)
end
end
# Accessor to the value of an EvenInt
val(x::EvenInt) = x.val
# A method working only on even numbers
grof(x::EvenInt) = println("good: $(val(x)) is even")
You'd use this like so:
julia> x = EvenInt(42)
EvenInt(42)
julia> grof(x)
good: 42 is even
julia> y = EvenInt(1)
ERROR: AssertionError: iseven(val)
Stacktrace:
[1] EvenInt(::Int64) at ./REPL[1]:5
[2] top-level scope at REPL[6]:1
but note that you can't do anything on EvenInts yet: you need to either unwrap them (using val() in this case), or define operations on them (a task which can be vastly simplified if you make EvenInt a subtype of one of the abstract number types and follow the relevant interface).
All integers multiplied by two are even, so redefine your function to take half the number it currently takes.
function grof2(halfx::Int)
x=2*halfx
println("good")
end

Are there subtile differences between one and multiline if expressions in Julia?

I am using Julia 1.1.1 and discovered something interesting yesterday.
Minimal example below
Consider the following code:
julia> if ((true)) true else false end
true
Works as intended
However, when attempting to do the following:
julia> function foo()
true
end
foo (generic function with 1 method)
julia> if ((foo())) (true,false) else (false,true) end
ERROR: syntax: space before "(" not allowed in "foo() ("
julia>
However, when writing the expression in the standard way it seems to work
julia> if ((foo()))
(true, false)
else
false
end
(true, false)
julia>
From my understanding from the following post Does Julia have a ternary conditional operator? I should be allowed to write if expressions in much the same way as ternaries and I usually can. However, for this case the ternary operator seems to be working as intended but not the if expression
julia> ((foo())) ? (true,false) : (false,true)
(true, false)
Does it exists a subtile difference between the two?
As noted in the comments by crstnbr the following syntax is allowed:
if ((foo())) true,false else false,true end
This does not seem to have anything to do with the if block per se. It is simply a syntax error.
Effectively, julia prohibits the syntax myfun (args) when calling a function (i.e. no space is allowed between the function name and the parentheses).
Since the output of a function, e.g., in this case foo(), may be another function, the same rule must apply to returned arguments. You wrapping your foo() function in infinite parentheses does nothing to resolve this, since the output of that expression is still asked to be evaluated via wrong syntax.
For example, note that:
julia> foo()()
ERROR: MethodError: objects of type Bool are not callable
Stacktrace:
[1] top-level scope at none:0
whereas
julia> foo() ()
ERROR: syntax: space before "(" not allowed in "foo() ("
Furthermore, as I mentioned in my comment above, regardless of the above, I personally would consider such terse if blocks very bad style, as well as a bad idea, as you have yourself just figured out. If you don't want to split into lines, it's is still a good idea, and much more readable, to use a semicolon at the end of the appropriate statements to show clear separation (both to yourself reading the code, and to the interpreter).
i.e.
if true; true, false; else; false, true; end
if foo(); true, false; else; false, true; end

Confusion with ' operator and bracketing where (v')*v becomes Ac_mul_B despite overloading

I am playing around with the idea of CoVectors in Julia and am getting some behaviour I didn't expect from the parser/compiler. I have defined a new CoVector type that is the ctranspose of any vector, and is just a simple decoration:
type CoVector{T<:AbstractVector}
v::T
end
They can be created (and uncreated) with ' using ctranspose:
import Base.ctranspose
function CoVector(T::DataType,d::Integer=0)
return CoVector(Array(T,d))
end
function Base.ctranspose(cv::CoVector)
return cv.v
end
function Base.ctranspose(v::AbstractVector)
return CoVector(v)
end
function Base.ctranspose(v::Vector) # this is already specialized in Base
return CoVector(v)
end
Next I want to define a simple dot product
function *(x::CoVector,y::AbstractVector)
return dot(x.v,y)
end
Which can work fine for:
v = [1,2,3]
cv = v'
cv*v
returns 14, and cv is a CoVector. But if I do
(v') * v
I get something different! In this case it is a single element array containing 14. How come parenthesis doesn't work how I expect?
In the end we see the expression gets expanded to Ac_mul_B which defaults to [dot(A,B)] and it seems that this interpretation is defined at the "operator" level.
Is this expected behaviour? Can Julia completely ignore my bracketing and change the expression as it wants? In Julia I like that I can override things in Base but is it also possible to make self-consistent changes to how operators are applied? I see the expression doesn't have head call but Symbol call... does this change in Julia 0.4? (I read somewhere that call is becoming more universal).
I guess I can fix the problem by redefining Ac_mul_B but I was very surprised that it was called at all, given my above definitions.

Why does this recursion MyFunc[n_] := MyFunc[n] = 2; end?

I don't understand, why does this recursion end:
In[27]:= MyFunc[n_] := MyFunc[n] = 2;
MyFunc[3]
Out[28]= 2
Shouldn't it be endless
MyFunc[3]
MyFunc[3] = 2
(MyFunc[3] = 2) = 2
and so on?
Why does this
MyFunc[n_] := MyFunc[n];
MyFunc[3]
During evaluation of In[31]:= $IterationLimit::itlim: Iteration limit of 4096 exceeded. >>
Out[33]= Hold[MyFunc[3]]
cause "iteration" limit error, not recursion limit?
My other answer glossed over some important details. Here's a second and, I hope, better one:
SetDelayed has the attribute HoldAll while Set has the attribute HoldFirst. So, your definition
MyFunc[n_] := MyFunc[n] = 2;
is stored with no part evaluated. Only when you call it, eg MyFunc[3] is the rhs evaluated, in this case to an expression involving Set, MyFunc[3] = 2. Since Set has attribute HoldFirst this rule is stored with its first argument (ie the lhs) unevaluated. At this stage MyFunc[3], the lhs of the Set expression is not re-evaluated. But if it were, Mathematica would find the rule MyFunc[3] = 2 and evaluate MyFunc[3] to 2 without using the rule with lhs MyFunc[n_].
Your second definition, ie
MyFunc[n_] := MyFunc[n];
is also stored unevaluated. However, when you call the function, eg myFunc[3], the rhs is evaluated. The rhs evaluates to MyFunc[3] or, if you like, another call to MyFunc. During the evaluation of MyFunc[3] Mathematica finds the stored rewrite rule MyFunc[n_] := MyFunc[n] and applies it. Repeatedly. Note that Mathematica regards this as iteration rather than recursion.
It's not entirely clear to me what evaluating the lhs of an expression might actually mean. Of course, a call such as MyFunc[3+4] will actually lead to MyFunc[7] being evaluated, as Mathematica greedily evaluates arguments to function calls.
In fact, when trying to understand what's going on here it might be easier to forget assignment and left- and right-hand sides and remember that everything is an expression and that, for example,
MyFunc[n_] := MyFunc[n] = 2;
is just a way of writing
SetDelayed[MyFunc[n_], MyFunc[n] = 2]

Resources