Since '+', '-', and the rest of the arithmetic operators must be, at heart, just function calls (I think), how are they defined? More specifically, how are they written such that they can look for arguments that precede them and follow them?
For example, the function '*', or multiply, in the expression 7 * 9 must look for the first argument 7 before it's called, and then the 9, it's second argument, which appears to be in the right place.
Most languages (not OCaml) require parentheses around arguments -- how have they gotten around this requirement in languages that do?
It sounds like you're asking about operator overloading, or at least reading into operator overloading will give you a pretty solid understanding on how arithmetic operations are defined in some languages. Here's a link to a nice tutorial on C++ operator overloading:
http://www.tutorialspoint.com/cplusplus/cpp_overloading.htm
In object-oriented world, this is called "operator overloading". It is just a kind of syntactic sugar, that enables you to call a + b, instead of a.+(b), that is actually the same method call.
Related
I am learning about higher order functions[HOF] and lambda in Kotlin.
I checked the Kotlin docs but didn't understand it, I found one benefit of HOF:
You can perform any operations on functions that are possible for other non-function values.
so, What are 'non-functional values'?
and What are those 'operations'?
In a higher order function if a lambda is taking two parameters and returning a value, then can't we just use a function for it?
and what is the real scenario when we have return a function?
I have seen real programs in Kotlin, but I haven't seen any use of lambda or HOF in them.
I want to understand why, else many of the features would just go unused.
It's just a part of the Kotlin syntax that makes it more concise and understandable.
For example, try to imagine this code without using lambdas and HOF like map, filter etc:
val sum = listOfInts.filter{it % 2 == 0}.map{it*it}.sumOf{it % 10}
Type-safe builders is a cool thing too.
These functions are widely used in many libraries and frameworks, like Compose by Google. The first thing I remembered - State hoisting pattern.
Forgive me if this is a kind of silly question, but I've been going through "Programming Elm" and one thing struck me as a little odd: in the text he shows an example of creating a record,
dog = { name = "Tucker", age = 11 }
and then right after that he shows a function that returns a record
haveBirthday d = { name = d.name, age = d.age + 1 }
To me, the syntax for both seems remarkably similar. How does the compiler know which is which? By the + on the right hand side of the function, that implies change, so it has to be a function? By the fact that there's an argument, d? Or is it that the difference between generating a record and a function is quite obvious, and it's just in this case that they seem so alike? Or is it that in some subtle way that I don't yet have the Zen to grasp, they are in fact the same thing? (That is, something like "everything is a function"?)
I've looked at https://elm-lang.org/docs/syntax#functions -- the docs are very user-friendly, but brief. Are there any other resources that give a more didactic view of the syntax (like this book does for Haskell)?
Thanks for any help along the way.
In an imperative language where "side-effects" are the norm, the term "function" is often used to describe what's more appropriately called a procedure or sub-routine. A set of instruction to be executed when called, and where order of execution and re-evaluation is essential because mutation and other side-effects can change anything from anywhere at any time.
In functional programming, however, the notion of a function is closer to the mathematical sense of the term, where its return value is computed entirely based on its arguments. This is especially true for a "pure" functional language like Elm, which normally does not allow "side-effects". That is, effects that interact with the "outside world" without going through the input arguments or return value. In a pure functional language it does not make sense to have a function that does not take any arguments, because it would always do the same thing, and computing the same value again and again is just wasteful. A function with no arguments is effectively just a value. And a function definition and value binding can therefore be distinguished solely based on whether or not it has any arguments.
But there are also many hybrid programming languages. Most functional languages are hybrids in fact, that allow side-effects but still stick close to the mathematical sense of a function. These languages also typically don't have functions without arguments, but use a special type called unit, or (), which has only one value, also called unit or (), which is used to denote a function that takes no significant input, or which returns nothing significant. Since unit has only one value, it carries no significant information.
Many functional languages don't even have functions that take multiple arguments either. In Elm and many other languages, a function takes exactly one argument. No more and no less, ever. You might have seen Elm code which appears to have multiple arguments, but that's all an illusion. Or syntax sugar as it's called in language theoretic lingo.
When you see a function definition like this:
add a b = a + b
that actual translates to this:
add = \a -> \b -> a + b
A function that takes an argument a, then returns another function which takes an argument b, which does the actual computation and returns the result. This is called currying.
Why do this? Because it makes it very convenient to partially apply functions. You can just leave out the last, or last few, arguments, then instead of an error you get a function back which you can fully apply later to get the result. This enables you to do some really handy things.
Let's look at an example. To fully apple add from above we'd just do:
add 2 3
The compiler actually parses this as (add 2) 3, so we've kind of done partial application already, but then immediately applied to another value. But what if we want to add 2 to a whole bunch of things and don't want write add 2 everywhere, because DRY and such? We write a function:
add2ToThings thing =
add 2 thing
(Ok, maybe a little bit contrived, but stay with me)
Partial application allows us to make this even shorter!
add2ToThings =
add 2
You see how that works? add 2 returns a function, and we just give that a name. There have been numerous books written about this marvellous idea in OOP, but they call it "dependency injection" and it's usually slightly more verbose when implemented with OOP techniques.
Anyway, say we have a list of "thing"s, we can get a new list with 2 added to everything by mapping over it like this:
List.map add2ToThings things
But we can do even better! Since add 2 is actually shorter than the name we gave it, we might as well just use it directly:
List.map (add 2) things
Ok, but then say we want to filter out every value that is exactly 5. We can actually partially apply infix operators too, but we have to surround the operator in parentheses to make it behave like an ordinary function:
List.filter ((/=) 5) (List.map (add 2) things)
This is starting to look a bit convoluted though, and reads backwards since we filter after we map. Fortunately we can use Elm's pipe operator |> to clean it up a bit:
things
|> List.map (add 2)
|> List.filter ((/=) 5)
The pipe operator was "discovered" because of partial application. Without that it couldn't have been implemented as an ordinary operator, but would have to be implemented as a special syntax rule in the parser. It's implementation is (essentially) just:
x |> f = f x
It takes an arbitrary argument on its left side and a function on its right side, then applies the function to the argument. And because of partial application we can conveniently get a function to pass in on the right side.
So in three lines of ordinary idiomatic Elm code we've used partial application four times. Without that, and currying, we'd have to write something like:
List.filter (\thing -> thing /= 5) (List.map (\thing -> add 2 thing) things)
Or we might want to write it with some variable bindings to make it more readable:
let
add2ToThings thing =
add 2 thing
thingsWith2Added =
List.map add2ToThings things
thingsWith2AddedAndWithout5 =
List.filter (\thing -> thing /= 5) thingWith2Added
in
thingsWith2AddedAndWithout5
And so that's why functional programming is awesome.
Is currying for functional programming the same as overloading for OO programming? If not, why? (with examples if possible)
Tks
Currying is not specific to functional programming, and overloading is not specific to object-oriented programming.
"Currying" is the use of functions to which you can pass fewer arguments than required to obtain a function of the remaining arguments. i.e. if we have a function plus which takes two integer arguments and returns their sum, then we can pass the single argument 1 to plus and the result is a function for adding 1 to things.
In Haskellish syntax (with function application by adjacency):
plusOne = plusCurried 1
three = plusOne 2
four = plusCurried 2 2
five = plusUncurried 2 3
In vaguely Cish syntax (with function application by parentheses):
plusOne = plusCurried(1)
three = plusOne(2)
four = plusCurried(2)(2)
five = plusUncurried(2, 3)
You can see in both of these examples that plusCurried is invoked on only 1 argument, and the result is something that can be bound to a variable and then invoked on another argument. The reason that you're thinking of currying as a functional-programming concept is that it sees the most use in functional languages whose syntax has application by adjacency, because in that syntax currying becomes very natural. The applications of plusCurried and plusUncurried to define four and five in the Haskellish syntax merge to become completely indistinguishable, so you can just have all functions be fully curried always (i.e. have every function be a function of exactly one argument, only some of them will return other functions that can then be applied to more arguments). Whereas in the Cish syntax with application by parenthesised argument lists, the definitions of four and five look completely different, so you need to distinguish between plusCurried and plusUncurried. Also, the imperative languages that led to today's object-oriented languages never had the ability to bind functions to variables or pass them to other functions (this is known as having first-class functions), and without that facility there's nothing you can actually do with a curried-function other than invoke it on all arguments, and so no point in having them. Some of today's OO languages still don't have first-class functions, or only gained them recently.
The term currying also refers to the process of turning a function of multiple arguments into one that takes a single argument and returns another function (which takes a single argument, and may return another function which ...), and "uncurrying" can refer to the process of doing the reverse conversion.
Overloading is an entirely unrelated concept. Overloading a name means giving multiple definitions with different characteristics (argument types, number of arguments, return type, etc), and have the compiler resolve which definition is meant by a given appearance of the name by the context in which it appears.
A fairly obvious example of this is that we could define plus to add integers, but also use the same name plus for adding floating point numbers, and we could potentially use it for concatenating strings, arrays, lists, etc, or to add vectors or matrices. All of these have very different implementations that have nothing to do with each other as far as the language implementation is concerned, but we just happened to give them the same name. The compiler is then responsible for figuring out that plus stringA stringB should call the string plus (and return a string), while plus intX intY should call the integer plus (and return an integer).
Again, there is no inherent reason why this concept is an "OO concept" rather than a functional programming concept. It simply happened that it fit quite naturally in statically typed object-oriented languages that were developed; if you're already resolving which method to call by the object that the method is invoked on, then it's a small stretch to allow more general overloading. Completely ad-hoc overloading (where you do nothing more than define the same name multiple times and trust the compiler to figure it out) doesn't fit as nicely in languages with first-class functions, because when you pass the overloaded name as a function itself you don't have the calling context to help you figure out which definition is intended (and programmers may get confused if what they really wanted was to pass all the overloaded definitions). Haskell developed type classes as a more principled way of using overloading; these effectively do allow you to pass all the overloaded definitions at once, and also allow the type system to express types a bit like "any type for which the functions f and g are defined".
In summary:
currying and overloading are completely unrelated
currying is about applying functions to fewer arguments than they require in order to get a function of the remaining arguments
overloading is about providing multiple definitions for the same name and having the compiler select which definition is used each time the name is used
neither currying nor overloading are specific to either functional programming or object-oriented programming; they each simply happen to be more widespread in historical languages of one kind or another because of the way the languages developed, causing them to be more useful or more obvious in one kind of language
No, they are entirely unrelated and dissimilar.
Overloading is a technique for allowing the same code to be used at different types -- often known in functional programming as polymorphism (of various forms).
A polymorphic function:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
Here, map is a function that operates on any list. It is polymorphic -- it works just as well with a list of Int as a list of trees of hashtables. It also is higher-order, in that it is a function that takes a function as an argument.
Currying is the transformation of a function that takes a structure of n arguments, into a chain of functions each taking one argument.
In curried languages, you can apply any function to some of its arguments, yielding a function that takes the rest of the arguments. The partially-applied function is a closure.
And you can transform a curried function into an uncurried one (and vice-versa) by applying the transformation invented by Curry and Schonfinkel.
curry :: ((a, b) -> c) -> a -> b -> c
-- curry converts an uncurried function to a curried function.
uncurry :: (a -> b -> c) -> (a, b) -> c
-- uncurry converts a curried function to a function on pairs.
Overloading is having multiple functions with the same name, having different parameters.
Currying is where you can take multiple parameters, and selectively set some, so you may just have one variable, for example.
So, if you have a graphing function in 3 dimensions, you may have:
justgraphit(double[] x, double[] y, double[] z), and you want to graph it.
By currying you could have:
var fx = justgraphit(xlist)(y)(z) where you have now set fx so that it now has two variables.
Then, later on, the user picks another axis (date) and you set the y, so now you have:
var fy = fx(ylist)(z)
Then, later you graph the information by just looping over some data and the only variability is the z parameter.
This makes complicated functions simpler as you don't have to keep passing what is largely set variables, so the readability increases.
I recently read:
"The expressions (++i) and (i++) have values and side effects.
The side effect is that the value in i is increased by 1.
The value of (i++) is the value before the increment and
the value of (++i) is the value after the increment,
but whether the increment or the evaluation takes place first,
is not part of C."
I know the evaluative step takes place first in Java... is it the same for all other languages?
At least in C++, operators can be overloaded, so the semantics of ++i and i++ are not guaranteed - they can in fact be overloaded to do very different things, and can even be made to do something that has nothing to do with increment. So the answer to your question is that no - in at least one language, the postfix and prefix ++ operator for classes can do whatever the programmer wishes.
But just because someone can do that, it doesn't mean they should. Since the pre- and post-increment operators have very well known semantics, (decent) C++ programmers try to not violate that, lest the code that uses them will be most surprised.
A good example of operator overloading in C++ is the STL iterators. Iterators to containers like linked lists define a class that overloads the preincrement and postincrement operators in such a way that it mimics a pointer (iterators in C++ are in fact a generalization of pointers).
Scheme uses a single namespace for all variables, regardless of whether they are bound to functions or other types of values. Common Lisp separates the two, such that the identifier "hello" may refer to a function in one context, and a string in another.
(Note 1: This question needs an example of the above; feel free to edit it and add one, or e-mail the original author with it and I will do so.)
However, in some contexts, such as passing functions as parameters to other functions, the programmer must explicitly distinguish that he's specifying a function variable, rather than a non-function variable, by using #', as in:
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
I have always considered this to be a bit of a wart, but I've recently run across an argument that this is actually a feature:
...the
important distinction actually lies in the syntax of forms, not in the
type of objects. Without knowing anything about the runtime values
involved, it is quite clear that the first element of a function form
must be a function. CL takes this fact and makes it a part of the
language, along with macro and special forms which also can (and must)
be determined statically. So my question is: why would you want the
names of functions and the names of variables to be in the same
namespace, when the primary use of function names is to appear where a
variable name would rarely want to appear?
Consider the case of class names: why should a class named FOO prevent
the use of variables named FOO? The only time I would be referring the
class by the name FOO is in contexts which expect a class name. If, on
the rare occasion I need to get the class object which is bound to the
class name FOO, there is FIND-CLASS.
This argument does make some sense to me from experience; there is a similar case in Haskell with field names, which are also functions used to access the fields. This is a bit awkward:
data Point = Point { x, y :: Double {- lots of other fields as well --} }
isOrigin p = (x p == 0) && (y p == 0)
This is solved by a bit of extra syntax, made especially nice by the NamedFieldPuns extension:
isOrigin2 Point{x,y} = (x == 0) && (y == 0)
So, to the question, beyond consistency, what are the advantages and disadvantages, both for Common Lisp vs. Scheme and in general, of a single namespace for all values versus separate ones for functions and non-function values?
The two different approaches have names: Lisp-1 and Lisp-2. A Lisp-1 has a single namespace for both variables and functions (as in Scheme) while a Lisp-2 has separate namespaces for variables and functions (as in Common Lisp). I mention this because you may not be aware of the terminology since you didn't refer to it in your question.
Wikipedia refers to this debate:
Whether a separate namespace for functions is an advantage is a source of contention in the Lisp community. It is usually referred to as the Lisp-1 vs. Lisp-2 debate. Lisp-1 refers to Scheme's model and Lisp-2 refers to Common Lisp's model. These names were coined in a 1988 paper by Richard P. Gabriel and Kent Pitman, which extensively compares the two approaches.
Gabriel and Pitman's paper titled Technical Issues of Separation in Function Cells and Value Cells addresses this very issue.
Actually, as outlined in the paper by Richard Gabriel and Kent Pitman, the debate is about Lisp-5 against Lisp-6, since there are several other namespaces already there, in the paper are mentioned type names, tag names, block names, and declaration names. edit: this seems to be incorrect, as Rainer points out in the comment: Scheme actually seems to be a Lisp-1. The following is largely unaffected by this error, though.
Whether a symbol denotes something to be executed or something to be referred to is always clear from the context. Throwing functions and variables into the same namespace is primarily a restriction: the programmer cannot use the same name for a thing and an action. What a Lisp-5 gets out of this is just that some syntactic overhead for referencing something from a different namespace than what the current context implies is avoided. edit: this is not the whole picture, just the surface.
I know that Lisp-5 proponents like the fact that functions are data, and that this is expressed in the language core. I like the fact that I can call a list "list" and a car "car" without confusing my compiler, and functions are a fundamentally special kind of data anyway. edit: this is my main point: separate namespaces are not a wart at all.
I also liked what Pascal Constanza had to say about this.
I've met a similar distinction in Python (unified namespace) vs Ruby (distinct namespaces for methods vs non-methods). In that context, I prefer Python's approach -- for example, with that approach, if I want to make a list of things, some of which are functions while others aren't, I don't have to do anything different with their names, depending on their "function-ness", for example. Similar considerations apply to all cases in which function objects are to be bandied around rather than called (arguments to, and return values from, higher-order functions, etc, etc).
Non-functions can be called, too (if their classes define __call__, in the case of Python -- a special case of "operator overloading") so the "contextual distinction" isn't necessarily clear, either.
However, my "lisp-oid" experience is/was mostly with Scheme rather than Common Lisp, so I may be subconsciously biased by the familiarity with the uniform namespace that in the end comes from that experience.
The name of a function in Scheme is just a variable with the function as its value. Whether I do (define x (y) (z y)) or (let ((x (lambda (y) (z y)))), I'm defining a function that I can call. So the idea that "a variable name would rarely want to appear there" is kind of specious as far as Scheme is concerned.
Scheme is a characteristically functional language, so treating functions as data is one of its tenets. Having functions be a type of their own that's stored like all other data is a way of carrying on the idea.
The biggest downside I see, at least for Common Lisp, is understandability. We can all agree that it uses different namespaces for variables and functions, but how many does it have? In PAIP, Norvig showed that it has "at least seven" namespaces.
When one of the language's classic books, written by a highly respected programmer, can't even say for certain in a published book, I think there's a problem. I don't have a problem with multiple namespaces, but I wish the language was, at the least, simple enough that somebody could understand this aspect of it entirely.
I'm comfortable using the same symbol for a variable and for a function, but in the more obscure areas I resort to using different names out of fear (colliding namespaces can be really hard to debug!), and that really should never be the case.
There's good things to both approaches. However, I find that when it matters, I prefer having both a function LIST and a a variable LIST than having to spell one of them incorrectly.