Can operators in Smalltalk be overloaded? - operator-overloading

Is it possible to overload operators in Smalltalk?
I am looking for tutorials/examples.
Thanks.

Method overloading is not possible in Smalltalk. Instead, a combination of method overriding and a technique called double dispatch is used to implement the same behavior as operator overloading in other languages.
You can find an example implementation in the mathematical operators +,*,/,- (which are binary messages in Smalltalk). Here is the idea: the implementation of Integer>>+ sends a message #addWithInteger: to its argument. The implementation of #addWithInteger: is implemented on each Magnitude subclass, such as to specialize addition of Int+Int, Float+Int, etc...

For most part, things that are operators in other languages are in Smalltalk unary or binary messages like +, *, /, ... etc. Classes are free to respond to those messages as they seem fit, so yes, you can redefine behavior of +, and you can also make instances of some non number classes understand and respond to it.
For instance look at the implementation of + in Point class.
One thing to note, := and ^ are not messages, so they can not redefined in a way described above.
Btw, for learning Smalltalk, one of the greatest resources of examples and code is the Smalltalk image. So I recommend that you fire up Smalltalk, and learn your way to browse through vast amount of examples that it contains.

There's no operators in smalltalk, except assignment. Everything is implemented in classes as methods. So if you want to change behaviour of = or + / - methods, just look at their implementors.
Or if you want to make instances of your class to understand those messages, just implement them.

The operator-overloading tag is defined on Stack Overflow as
a feature of a programming language that allows custom implementations for operators depending on the types of the operands involved. Some languages allow new operators to be defined while others only allow redefinition of existing ones.
In Smalltalk
All types are defined as classes of object *
All operators are methods *
All methods are executed by the receiver of the message with the method's name
All methods can be over-ridden
So any operator, operating on any operand, can be over-ridden by any developer.
Here are some examples:
Objects of Class Float, Class SmallInt, Class Fraction and Class Point can all respond to a + message. They can interroperate with one another, too.
aFloat := 3.1415 .
aSmallInt := '6' .
aPoint := 3#3 .
aFraction := 22/7 .
"send the + aSmallInt message to aFraction"
aSum := aFraction + aSmallInt Evaluates to: 64/7
"send the + aFraction message to aSmallInt"
aSum := aSmallInt + aFraction Evaluates to: 64/7
aSum := aFloat + aFraction
aSum := aFraction + aFloat These evaluate to: 6.284357142857143
aSum := aFloat + aSmallInt
aSum := aSmallInt + aFloat These evaluate to: 9.1415
aSum := aPoint + aSmallInt
aSum := aSmallInt + aPoint These evaluate to: 9#9
In effect, we have 8 different implementations of the + operator on display here, each customised to deal with the types of the operands involved.
The caveats:
* Objects are not strongly typed. Any variable of one type can be changed to any other type, and the system will not raise an exception. An object can start as an object of Class SmallInt and then be changed to a ByteString or a Dictionary, and the system will not raise the slightest warning. Until it is sent a message that it does not understand.
There are 6 primitives that are not an object or Class of object:
true, false, nil, etc.
There are two operators which are, in effect, syntactic sugar for named methods.

Smalltalk doesn't have operators but you can achieve a similar thing via method definition/overriding:
Object subclass: Foo [
+ anObject [
"define new behavior for + here"
]
]

Related

Spark Scala Why is it that I can make certain function calls with parenthesis and certain function calls without parenthesis [duplicate]

What are the precise rules for when you can omit (omit) parentheses, dots, braces, = (functions), etc.?
For example,
(service.findAllPresentations.get.first.votes.size) must be equalTo(2).
service is my object
def findAllPresentations: Option[List[Presentation]]
votes returns List[Vote]
must and be are both functions of specs
Why can't I go:
(service findAllPresentations get first votes size) must be equalTo(2)
?
The compiler error is:
"RestServicesSpecTest.this.service.findAllPresentations
of type
Option[List[com.sharca.Presentation]]
does not take parameters"
Why does it think I'm trying to pass in a parameter? Why must I use dots for every method call?
Why must (service.findAllPresentations get first votes size) be equalTo(2) result in:
"not found: value first"
Yet, the "must be equalTo 2" of
(service.findAllPresentations.get.first.votes.size) must be equalTo 2, that is, method chaining works fine? - object chain chain chain param.
I've looked through the Scala book and website and can't really find a comprehensive explanation.
Is it in fact, as Rob H explains in Stack Overflow question Which characters can I omit in Scala?, that the only valid use-case for omitting the '.' is for "operand operator operand" style operations, and not for method chaining?
You seem to have stumbled upon the answer. Anyway, I'll try to make it clear.
You can omit dot when using the prefix, infix and postfix notations -- the so called operator notation. While using the operator notation, and only then, you can omit the parenthesis if there is less than two parameters passed to the method.
Now, the operator notation is a notation for method-call, which means it can't be used in the absence of the object which is being called.
I'll briefly detail the notations.
Prefix:
Only ~, !, + and - can be used in prefix notation. This is the notation you are using when you write !flag or val liability = -debt.
Infix:
That's the notation where the method appears between an object and it's parameters. The arithmetic operators all fit here.
Postfix (also suffix):
That notation is used when the method follows an object and receives no parameters. For example, you can write list tail, and that's postfix notation.
You can chain infix notation calls without problem, as long as no method is curried. For example, I like to use the following style:
(list
filter (...)
map (...)
mkString ", "
)
That's the same thing as:
list filter (...) map (...) mkString ", "
Now, why am I using parenthesis here, if filter and map take a single parameter? It's because I'm passing anonymous functions to them. I can't mix anonymous functions definitions with infix style because I need a boundary for the end of my anonymous function. Also, the parameter definition of the anonymous function might be interpreted as the last parameter to the infix method.
You can use infix with multiple parameters:
string substring (start, end) map (_ toInt) mkString ("<", ", ", ">")
Curried functions are hard to use with infix notation. The folding functions are a clear example of that:
(0 /: list) ((cnt, string) => cnt + string.size)
(list foldLeft 0) ((cnt, string) => cnt + string.size)
You need to use parenthesis outside the infix call. I'm not sure the exact rules at play here.
Now, let's talk about postfix. Postfix can be hard to use, because it can never be used anywhere except the end of an expression. For example, you can't do the following:
list tail map (...)
Because tail does not appear at the end of the expression. You can't do this either:
list tail length
You could use infix notation by using parenthesis to mark end of expressions:
(list tail) map (...)
(list tail) length
Note that postfix notation is discouraged because it may be unsafe.
I hope this has cleared all the doubts. If not, just drop a comment and I'll see what I can do to improve it.
Class definitions:
val or var can be omitted from class parameters which will make the parameter private.
Adding var or val will cause it to be public (that is, method accessors and mutators are generated).
{} can be omitted if the class has no body, that is,
class EmptyClass
Class instantiation:
Generic parameters can be omitted if they can be inferred by the compiler. However note, if your types don't match, then the type parameter is always infered so that it matches. So without specifying the type, you may not get what you expect - that is, given
class D[T](val x:T, val y:T);
This will give you a type error (Int found, expected String)
var zz = new D[String]("Hi1", 1) // type error
Whereas this works fine:
var z = new D("Hi1", 1)
== D{def x: Any; def y: Any}
Because the type parameter, T, is inferred as the least common supertype of the two - Any.
Function definitions:
= can be dropped if the function returns Unit (nothing).
{} for the function body can be dropped if the function is a single statement, but only if the statement returns a value (you need the = sign), that is,
def returnAString = "Hi!"
but this doesn't work:
def returnAString "Hi!" // Compile error - '=' expected but string literal found."
The return type of the function can be omitted if it can be inferred (a recursive method must have its return type specified).
() can be dropped if the function doesn't take any arguments, that is,
def endOfString {
return "myDog".substring(2,1)
}
which by convention is reserved for methods which have no side effects - more on that later.
() isn't actually dropped per se when defining a pass by name paramenter, but it is actually a quite semantically different notation, that is,
def myOp(passByNameString: => String)
Says myOp takes a pass-by-name parameter, which results in a String (that is, it can be a code block which returns a string) as opposed to function parameters,
def myOp(functionParam: () => String)
which says myOp takes a function which has zero parameters and returns a String.
(Mind you, pass-by-name parameters get compiled into functions; it just makes the syntax nicer.)
() can be dropped in the function parameter definition if the function only takes one argument, for example:
def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }
But if it takes more than one argument, you must include the ():
def myOp2(passByNameString:(Int, String) => String) { .. }
Statements:
. can be dropped to use operator notation, which can only be used for infix operators (operators of methods that take arguments). See Daniel's answer for more information.
. can also be dropped for postfix functions
list tail
() can be dropped for postfix operators
list.tail
() cannot be used with methods defined as:
def aMethod = "hi!" // Missing () on method definition
aMethod // Works
aMethod() // Compile error when calling method
Because this notation is reserved by convention for methods that have no side effects, like List#tail (that is, the invocation of a function with no side effects means that the function has no observable effect, except for its return value).
() can be dropped for operator notation when passing in a single argument
() may be required to use postfix operators which aren't at the end of a statement
() may be required to designate nested statements, ends of anonymous functions or for operators which take more than one parameter
When calling a function which takes a function, you cannot omit the () from the inner function definition, for example:
def myOp3(paramFunc0:() => String) {
println(paramFunc0)
}
myOp3(() => "myop3") // Works
myOp3(=> "myop3") // Doesn't work
When calling a function that takes a by-name parameter, you cannot specify the argument as a parameter-less anonymous function. For example, given:
def myOp2(passByNameString:Int => String) {
println(passByNameString)
}
You must call it as:
myOp("myop3")
or
myOp({
val source = sourceProvider.source
val p = myObject.findNameFromSource(source)
p
})
but not:
myOp(() => "myop3") // Doesn't work
IMO, overuse of dropping return types can be harmful for code to be re-used. Just look at specification for a good example of reduced readability due to lack of explicit information in the code. The number of levels of indirection to actually figure out what the type of a variable is can be nuts. Hopefully better tools can avert this problem and keep our code concise.
(OK, in the quest to compile a more complete, concise answer (if I've missed anything, or gotten something wrong/inaccurate please comment), I have added to the beginning of the answer. Please note this isn't a language specification, so I'm not trying to make it exactly academically correct - just more like a reference card.)
A collection of quotes giving insight into the various conditions...
Personally, I thought there'd be more in the specification. I'm sure there must be, I'm just not searching for the right words...
There are a couple of sources however, and I've collected them together, but nothing really complete / comprehensive / understandable / that explains the above problems to me...:
"If a method body has more than one
expression, you must surround it with
curly braces {…}. You can omit the
braces if the method body has just one
expression."
From chapter 2, "Type Less, Do More", of Programming Scala:
"The body of the upper method comes
after the equals sign ‘=’. Why an
equals sign? Why not just curly braces
{…}, like in Java? Because semicolons,
function return types, method
arguments lists, and even the curly
braces are sometimes omitted, using an
equals sign prevents several possible
parsing ambiguities. Using an equals
sign also reminds us that even
functions are values in Scala, which
is consistent with Scala’s support of
functional programming, described in
more detail in Chapter 8, Functional
Programming in Scala."
From chapter 1, "Zero to Sixty: Introducing Scala", of Programming Scala:
"A function with no parameters can be
declared without parentheses, in which
case it must be called with no
parentheses. This provides support for
the Uniform Access Principle, such
that the caller does not know if the
symbol is a variable or a function
with no parameters.
The function body is preceded by "="
if it returns a value (i.e. the return
type is something other than Unit),
but the return type and the "=" can be
omitted when the type is Unit (i.e. it
looks like a procedure as opposed to a
function).
Braces around the body are not
required (if the body is a single
expression); more precisely, the body
of a function is just an expression,
and any expression with multiple parts
must be enclosed in braces (an
expression with one part may
optionally be enclosed in braces)."
"Functions with zero or one argument
can be called without the dot and
parentheses. But any expression can
have parentheses around it, so you can
omit the dot and still use
parentheses.
And since you can use braces anywhere
you can use parentheses, you can omit
the dot and put in braces, which can
contain multiple statements.
Functions with no arguments can be
called without the parentheses. For
example, the length() function on
String can be invoked as "abc".length
rather than "abc".length(). If the
function is a Scala function defined
without parentheses, then the function
must be called without parentheses.
By convention, functions with no
arguments that have side effects, such
as println, are called with
parentheses; those without side
effects are called without
parentheses."
From blog post Scala Syntax Primer:
"A procedure definition is a function
definition where the result type and
the equals sign are omitted; its
defining expression must be a block.
E.g., def f (ps) {stats} is
equivalent to def f (ps): Unit =
{stats}.
Example 4.6.3 Here is a declaration
and a de?nition of a procedure named
write:
trait Writer {
def write(str: String)
}
object Terminal extends Writer {
def write(str: String) { System.out.println(str) }
}
The code above is implicitly completed
to the following code:
trait Writer {
def write(str: String): Unit
}
object Terminal extends Writer {
def write(str: String): Unit = { System.out.println(str) }
}"
From the language specification:
"With methods which only take a single
parameter, Scala allows the developer
to replace the . with a space and omit
the parentheses, enabling the operator
syntax shown in our insertion operator
example. This syntax is used in other
places in the Scala API, such as
constructing Range instances:
val firstTen:Range = 0 to 9
Here again, to(Int) is a vanilla
method declared inside a class
(there’s actually some more implicit
type conversions here, but you get the
drift)."
From Scala for Java Refugees Part 6: Getting Over Java:
"Now, when you try "m 0", Scala
discards it being a unary operator, on
the grounds of not being a valid one
(~, !, - and +). It finds that "m" is
a valid object -- it is a function,
not a method, and all functions are
objects.
As "0" is not a valid Scala
identifier, it cannot be neither an
infix nor a postfix operator.
Therefore, Scala complains that it
expected ";" -- which would separate
two (almost) valid expressions: "m"
and "0". If you inserted it, then it
would complain that m requires either
an argument, or, failing that, a "_"
to turn it into a partially applied
function."
"I believe the operator syntax style
works only when you've got an explicit
object on the left-hand side. The
syntax is intended to let you express
"operand operator operand" style
operations in a natural way."
Which characters can I omit in Scala?
But what also confuses me is this quote:
"There needs to be an object to
receive a method call. For instance,
you cannot do “println “Hello World!”"
as the println needs an object
recipient. You can do “Console
println “Hello World!”" which
satisfies the need."
Because as far as I can see, there is an object to receive the call...
I find it easier to follow this rule of thumb: in expressions spaces alternate between methods and parameters. In your example, (service.findAllPresentations.get.first.votes.size) must be equalTo(2) parses as (service.findAllPresentations.get.first.votes.size).must(be)(equalTo(2)). Note that the parentheses around the 2 have a higher associativity than the spaces. Dots also have higher associativity, so (service.findAllPresentations.get.first.votes.size) must be.equalTo(2)would parse as (service.findAllPresentations.get.first.votes.size).must(be.equalTo(2)).
service findAllPresentations get first votes size must be equalTo 2 parses as service.findAllPresentations(get).first(votes).size(must).be(equalTo).2.
Actually, on second reading, maybe this is the key:
With methods which only take a single
parameter, Scala allows the developer
to replace the . with a space and omit
the parentheses
As mentioned on the blog post: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6 .
So perhaps this is actually a very strict "syntax sugar" which only works where you are effectively calling a method, on an object, which takes one parameter. e.g.
1 + 2
1.+(2)
And nothing else.
This would explain my examples in the question.
But as I said, if someone could point out to be exactly where in the language spec this is specified, would be great appreciated.
Ok, some nice fellow (paulp_ from #scala) has pointed out where in the language spec this information is:
6.12.3:
Precedence and associativity of
operators determine the grouping of
parts of an expression as follows.
If there are several infix operations in an expression, then
operators with higher precedence bind
more closely than operators with lower
precedence.
If there are consecutive infix operations e0 op1 e1 op2 . . .opn en
with operators op1, . . . , opn of the
same precedence, then all these
operators must have the same
associativity. If all operators are
left-associative, the sequence is
interpreted as (. . . (e0 op1 e1) op2
. . .) opn en. Otherwise, if all
operators are rightassociative, the
sequence is interpreted as e0 op1 (e1
op2 (. . .opn en) . . .).
Postfix operators always have lower precedence than infix operators. E.g.
e1 op1 e2 op2 is always equivalent to
(e1 op1 e2) op2.
The right-hand operand of a
left-associative operator may consist
of several arguments enclosed in
parentheses, e.g. e op (e1, . . .
,en). This expression is then
interpreted as e.op(e1, . . . ,en).
A left-associative binary operation e1
op e2 is interpreted as e1.op(e2). If
op is rightassociative, the same
operation is interpreted as { val
x=e1; e2.op(x ) }, where x is a fresh
name.
Hmm - to me it doesn't mesh with what I'm seeing or I just don't understand it ;)
There aren't any. You will likely receive advice around whether or not the function has side-effects. This is bogus. The correction is to not use side-effects to the reasonable extent permitted by Scala. To the extent that it cannot, then all bets are off. All bets. Using parentheses is an element of the set "all" and is superfluous. It does not provide any value once all bets are off.
This advice is essentially an attempt at an effect system that fails (not to be confused with: is less useful than other effect systems).
Try not to side-effect. After that, accept that all bets are off. Hiding behind a de facto syntactic notation for an effect system can and does, only cause harm.

Why is "reduce" an infix operator in Chapel?

According to this manual page, we can use reduce to perform reduction like
summation (+):
var a = (+ reduce A) / num;
var b = + reduce abs(A);
var c = sqrt(+ reduce A**2);
and maximum value/location:
var (maxVal, maxLoc) = maxloc reduce zip(A, A.domain);
Here, Chapel defines reduce to be an infix operator rather than a function (e.g., reduce( A, + )). IMHO, the latter form seems to be a bit more readable because the arguments are always separated by parentheses. So I am wondering if there is some reason for this choice (e.g., to simplify some parallel syntax) or just a matter of history (convention)?
I'd say the answer is a matter of history / convention. A lot of Chapel's array and domain features were heavily inspired by the ZPL language from the University of Washington, and I believe this syntax was taken reasonably directly from ZPL.
At the time, we didn't have a notion of passing things like functions and operators around in Chapel, which is probably one of the reasons that we didn't consider more of a function-based approach. (Even now, first-class function support in Chapel is still somewhat in its infancy, and I don't believe we have a way to pass operators around).
I'd also say that Chapel is a language that generally favors syntax for key patterns rather than taking more of a "make everything look like a function / method call" approach (e.g., ranges are supported via a literal syntax and several key operators rather than using an object type with methods).
None of this is to say that the choice was obviously right or couldn't be reconsidered.

Why we cannot pattern match on Set/Type in Coq/Agda/Idris?

Think about a function which accepts a Set, and returns its byte length, named byteLength:
byteLength : Set -> Maybe Nat
and if I want to implement this function directly, I need to pattern match on the type argument:
byteLength Char = Just 1
byteLength Double = Just 8
byteLength _ = Nothing
but the above code doesn't compile since pattern matching on Set/Type is not allowed.
so we have to define an Interface as a workaround
Interface ByteLength a where
byteLength : Nat
implement ByteLength Char where
byteLength = 1
and in a more general way, maybe we can use something like TypeRep to do the similar thing and pattern match on TypeRep. but TypeRep is also defined as an Interface.
I think using Interface and using forall is very different, since Interface means "for some types", and forall means "for all types".
I'm wondering Why these DT languages don't support pattern matching on Set/Type, is there some special reason which I don't know?
In Agda, Idris, Haskell, and many other languages quantification over types is parametric (as opposed to ad-hoc polymorphism where you are allowed to match on types). From an implementation point of view, this means the compiler can erase all types from the program, since a functions can never computationally depend on an argument of type Set. Being able to erase types is especially important in dependently typed languages since types can often become huge expressions.
From a more theoretical point of view, parametric polymorphism is nice because it allows us to deduce certain properties of a function by just looking at its type, described eloquently as "free theorems" by Phil Wadler. I could try to give you the gist of the paper, but you should really just go and read it instead.
Of course, sometimes ad-hoc polymorphism is required to implement a function, which is why Haskell and Idris have type classes (Agda has a similar feature called instance arguments, and Coq has canonical structures as well as type classes). For example, in Agda you can define a record like this:
record ByteLength (A : Set) : Set where
field
theByteLength : Nat
open ByteLength
byteLength : (A : Set) {{_ : ByteLength A}} -> Nat
byteLength A {{bl}} = bl .theByteLength
and then you can define the byteLength function for various types by defining instances:
instance
byteLengthChar : ByteLength Char
byteLengthChar .theByteLength = 1
byteLengthDouble : ByteLength Double
byteLengthDouble .theByteLength = 8
With this code, byteLength Char evaluates to 1 and byteLength Double evaluates to 8, while it will raise a type error for any other type.

Is the uplus function useful?

This is a rhetorical question about the uplus function in MATLAB, or its corresponding operator, the unary plus +.
Is there a case where this operator is useful? Even better, is there a case where this operator is necessary?
It is not necessary, a language without a unary plus does not allow to write +1. Obviously you could also write 1 but when importing data which always writes the + or - it's very nice to have.
Searching some source codes, I found a curious use of +
A=+A
which replaced the code:
if ~isnumeric(A)
A=double(A);
end
It casts chars and logicals to double, but all numeric data types remain untouched.
It can be useful when defining new numeric types.
Suppose you define quaternion and overload uplus:
classdef quaternion
...
end
Then in your code you can write:
x = quaternion(...);
y = [+x, -x];
z = +quaternion.Inf;
t = -quaternion.Inf;
If you don't you cannot have same syntax as for other numeric.
PS: To the question "is it useful" (in the sence mandatory for some syntaxes) ... well I can't find any reason ... but sometimes writting '+x' make things clearer when reading back the code.
I'm not sure if this fully constitutes "useful" or if it's the best programming practice, but in some cases, one may wish to use the unary + for symmetry/clarity reasons. There's probably a better example, but I'm thinking of something like this:
A = [+1 -1 +1;
-1 +1 -1;
+1 -1 +1];
As for the uplus function, it's kind of a NOOP for numeric operations. If one writes a function that requires a function handle input to specify an operation to perform, it might be useful to have do nothing option.
Lastly, numeric operators can be overloaded for other classes. The uplus function could have more use in other built-in classes or even one you might want write yourself.

What is the difference between = and := in Scala?

What is the difference between = and := in Scala?
I have googled extensively for "scala colon-equals", but was unable to find anything definitive.
= in scala is the actual assignment operator -- it does a handful of specific things that for the most part you don't have control over, such as
Giving a val or var a value when it's created
Changing the value of a var
Changing the value of a field on a class
Making a type alias
Probably others
:= is not a built-in operator -- anyone can overload it and define it to mean whatever they like. The reason people like to use := is because it looks very assignmenty and is used as an assignment operator in other languages.
So, if you're trying to find out what := means in the particular library you're using... my advice is look through the Scaladocs (if they exist) for a method named :=.
from Martin Odersky:
Initially we had colon-equals for assignment—just as in Pascal, Modula, and Ada—and a single equals sign for equality. A lot of programming theorists would argue that that's the right way to do it. Assignment is not equality, and you should therefore use a different symbol for assignment. But then I tried it out with some people coming from Java. The reaction I got was, "Well, this looks like an interesting language. But why do you write colon-equals? What is it?" And I explained that its like that in Pascal. They said, "Now I understand, but I don't understand why you insist on doing that." Then I realized this is not something we wanted to insist on. We didn't want to say, "We have a better language because we write colon-equals instead of equals for assignment." It's a totally minor point, and people can get used to either approach. So we decided to not fight convention in these minor things, when there were other places where we did want to make a difference.
from The Goals of Scala's Design
= performs assignment. := is not defined in the standard library or the language specification. It's a name that is free for other libraries or your code to use, if you wish.
Scala allows for operator overloading, where you can define the behaviour of an operator just like you could write a method.
As in other languages, = is an assignment operator.
The is no standard operator I'm aware of called :=, but could define one with this name. If you see an operator like this, you should check up the documentation of whatever you're looking at, or search for where that operator is defined.
There is a lot you can do with Scala operators. You can essentially make an operator out of virtually any characters you like.