Wikipedia says that Reverse().Aggregate(initval, func) is a Right Fold. This sounds like it is not true, but rather a cheap cop out... Can anyone comment on this issue? Does C# have right folds?
Take definition of right fold and check whether Reverse().Aggregate(initval, func) fits into it.
Definition:
Combining the first element with the results of combining the rest is called a right fold
So if you want to calc the sum of (1, 2, 3). If you just Aggregate the evaluation will be (1 + 2) + 3. If you Reverse().Aggregate then it will be (3 + 2) + 1, which perfectly fits the definition.
The question might be is it efficient because Reverse is expensive operation, but functionally it is perfect right fold.
Aggregate is a true left fold. Aggregating a reversed list has the same semantics as a complete (non-lazy) right fold on any reversible list.
Related
Curry & Fold - what are the etymologies in the programmatic sense?
I do not see how any of the English meanings of these homonyms is related to the functionality of these terms.
If you had to rename them to something more obvious - how would you do it?
Curry is the last name of Haskell Curry, a prominent 20th century logician after whom Haskell got its name.
And "folding" simply because the fold operator figuratively represents folding, like a hand of cards can be folded to look like a single card. Think of foldr (+) 0 [1,2,3] == 6 as a hand of cards 1, 2 and 3 folded into a single card 6.
The word "reducing", which also means folding, can be illustrated using a similar analogy.
Of course, Haskell is more magic than even the bluffiest and luckiest game of poker, so folds in functional programming can actually produce a deck of cards that holds more cards than the hand it was folded from, or cards can be folded into cats, etc: foldr (\i, acc -> [show i,show i,show i] ++ acc) [] [1,2,3] == ["1","1","1","2","2","2","3","3","3"]. Therefore what started out as folding eventually evolved into an extremely universal operator that can produce map as well as filter etc, so don't get too carried away with the poker comparison and etymology.
As to what to name them to: renaming a dead person might not be the most ethical thing to do. The poor guy is so successful BOTH of his names are used for big things, and then you want to deprive him posthumously of his joy and rename him to something else? Unless perhaps that something else is Newton Watt Scoville or Kelvin Celsius Ângström, I'd seriously not attempt a rename.
However if you meant renaming the programming concept: it could instead be referred to by the name "ricing" in my hungry opinion. But Mr. Curry might still feel intimidated.
Folding could actually be renamed to bluffing, if you're not fulfilled by the multitude of presently available names for it — thanks to som-snytt for the constructive idea.
I believe that the "fold" term comes mainly from the use of the word "fold" in phrases like "to fold into..." which is a term most commonly used by chefs, I believe (I watch a lot of cooking shows...). We use it in the context of functional programming because we say that, for example, for lists, the head of the list is "folded into" the resulting of folding the tail. For example, the function foldr is a "recipe" for how to "cook" a list, and part of that recipe is "fold this into that", if you like.
The oldest reference to "folding" that I could find on the internet in the context of functional programming in this report, published in 1985 by the University of Cambridge, which has this to say:
The function gather applies a function of two arguments “between” each element of a list and a terminal value. [...] This function is also known as reduce or fold in other languages.
So clearly the term "fold" was at least somewhat common even 30 years ago!
I come from Scala. So I frequently do stuff like:
println((1 to 10).filter(_ < 3).map(x => x*x))
In Haskell, after I discovered I can get rid of all the nested parenthesis using $ and ., I recently found myself writing:
putStrLn . show . map (**2) . filter (< 3) $ [1..10]
Now, this works, but the code reads right-to-left, and unless I shift to Arabic, this is difficult for me to reason about.
Is there any other trick that makes me chain the functions from left to right? Or this is just the Haskell idiomatic way?
Unfortunately, it's the Haskell idiomatic way. But the & operator might do what you want.
import Data.Function ((&))
[1..10] & filter (< 3) & map (**2) & show & putStrLn
Essentially, (&) = flip ($). Likewise, Control.Arrow.(>>>) = flip (.)
UPDATE (6+ months later): I have to admit, this issue is a big source of frustration for me and I have been toying with this potential solution:
https://gist.github.com/obadz/9f322df8ba6c8a9767683d2f86af8589#file-directionalops-hs-L81
Yes, it is idiomatic Haskell. Not Arabic, but rather Mathematic, derived from the syntax for composition. See also Haskell composition (.) vs F#'s pipe forward operator (|>).
Still, even in Haskell you sometimes prefer to write your calls in the other direction, and you'll find a few libraries (e.g. Data.Function since base 4.8.0) who have defined
(&) = flip ($)
so that you can express your call as
[1..10] & filter (< 3) & map (**2) & show & putStrLn
Why not make a new operator?
(#) :: a -> (a -> b) -> b
(#) = flip id
Now you can just write
[1..10] # filter (< 3) # map (**2) # show # putStrLn
This is the equivalent of the (&) operator from Data.Function.
The following PL code does not work under #lang pl:
Edited code according to Alexis Kings answer
(define-type BINTREE
[Leaf Number]
[Node BINTREE BINTREE])
(: retrieve-leaf : BINTREE -> Number)
(define (retrieve-leaf btree)
(match btree
[(Leaf number) number])
What i'd like to achieve is as follows:
Receive a BINTREE as input
Check whether the tree is simply a leaf
Return the leaf numerical value
This might be a basic question but how would I go about solving this?
EDIT: The above seems to work if cases is used instead of match.
Why is that?
As you've discovered, match and cases are two similar but separate
things. The first is used for general Racket values, and the second is
used for things that you defined with define-type. Unfortunately,
they don't mix well in either direction, so if you have a defined type
then you need to use cases.
As for the reason for that, it's kind of complicated... One thing is
that the pl language was made well before match was powerful enough
to deal with arbitrary values conveniently. It does now, but it cannot
be easily tweaked to do what cases does: the idea behind define-type
is to make programming simple by making it mandatory to use just
cases for such values --- there are no field accessors, no predicates
for the variants (just for the whole type), and certainly no mutation.
Still, it is possible to do anything you need with just cases. If you
read around, the core idea is to mimic disjoint union types in HM
languages like ML and Haskell, and with only cases pattern matching
available, many functions are easy to start since there's a single way
to deal with them.
match and Typed Racket got closer to being able to do these things,
but it's still not really powerful enough to do all of that --- which is
why cases will stay separate from match in the near future.
As a side note, this is in contrast to what I want --- I know that this
is often a point of confusion, so I'd love to have just match used
throughout. Maybe I'll break at some point and hack things so that
cases is also called match, and the contents of the branches would
be used to guess if you really need the real match or the cases
version. But that would really be a crude hack.
I think you're on the right track, but your match syntax isn't correct. It should look like this:
(: retrieve-leaf : BINTREE -> Number)
(define (retrieve-leaf btree)
(match btree
[(Leaf number) number]))
The match pattern clauses must be inside the match form. Additionally, number is just a binding, not a procedure, so it doesn't need to be in parens.
I'm trying to pick up some scala. Reading through examples I came across this impossible-to-google nugget:
case 3 => l ::: List(3)
What does the triple colon accomplish?
Concatenates two lists - javadoc
To add to gkamal's answer, it's important to understand that methods whose names end in a colon are right-associative. So writing l ::: List(3) is the same as writing List(3).:::(l). In this case it doesn't matter since both operands are lists, but in general you'll need this knowledge to find such methods in the scaladocs.
It also helps to know that the scaladocs have a comprehensive index of all methods (and classes, etc) with symbolic names. You can reach it by clicking on the # in the upper-left corner.
I note that Scheme and Lisp (I guess) support circular lists, and I have used circular lists in C/C++ to 'simplify' the insertion and deletion of elements, but what are they good for?
Scheme ensures that they can be built and processed, but for what?
Is there a 'killer' data structure that needs to be circular or tail-circular?
Saying it supports 'circular lists' is a bit much. You can build all kinds of circular data structures in Lisp. Like in many programming languages. There is not much special about Lisp in this respect. Take your typical 'Algorithms and Datastructure' book and implement any circular data structure: graphs, rings, ... What some Lisps offer is that one can print and read circular data structures. The support for this is because in typical Lisp programming domains circular data structures are common: parsers, relational expressions, networks of words, plans, ...
It is quite common that data structures contain cycles. Real 'circular lists' are not that often used. For example think of a task scheduler which runs a task and after some time switches to the next. The list of tasks can be circular so that after the 'last' task the scheduler takes the 'first' task. In fact there is no 'last' and 'first' - it is just a circular list of tasks and the scheduler runs them without end. You could also have a list of windows in a window system and with some key command you would switch to the next window. The list of windows could be circular.
Lists are useful when you need a cheap next operation and the size of the data structure is unknown in advance. You can always add another node to the list or remove a node from a list. Usual implementations of lists make getting the next node and adding/removing an item cheap. Getting the next element from an array is also relatively simple (increase the index, at the last index go to the first index), but adding/removing elements usually needs more expensive shift operations.
Also since it is easy to build circular data structures, one just might do it during interactive programming. If you then print a circular data structure with the built-in routines it would be a good idea if the printer can handle it, since otherwise it may print a circular list forever...
Have you ever played Monopoly?
Without playing games with counters and modulo and such, how would you represent the Monopoly board in a computer implementation of the game? A circular list is a natural.
For example a double linked list data structure is "circular" in the Scheme/LISP point of view, i.e. if you try to print the cons-structure out you get backreferences, i.e. "cycles". So it's not really about having data structures that look like "rings", any data structure where you have some kind of backpointers is "circular" from the Scheme/LISP perspective.
A "normal" LISP list is single linked, which means that a destructive mutation to remove an item from inside the list is an O(n) operation; for double linked lists it is O(1). That's the "killer feature" of double linked lists, which are "circular" in the Scheme/LISP context.
Adding and removing elements to the beginning of a list is cheap. To
add or remove an element from the end of a list, you have to traverse
the whole list.
With a circular list, you can have a sort of fixed-length queue.
Setup a circular list of length 5:
> (import (srfi :1 lists))
> (define q (circular-list 1 2 3 4 5))
Let's add a number to the list:
> (set-car! q 6)
Now, let's make that the last element of the list:
> (set! q (cdr q))
Display the list:
> (take q 5)
(2 3 4 5 6)
So you can view this as a queue where elements enter at the end of the list and are removed from the head.
Let's add 7 to the list:
> (set-car! q 7)
> (set! q (cdr q))
> (take q 5)
(3 4 5 6 7)
Etc...
Anyways, this is one way that I've used circular-lists.
I use this technique in an OpenGL demo which I ported from an example in the Processing book.
Ed
One use of circular lists is to "repeat" values when using the srfi-1 version of map. For example, to add val to each element of lst, we could write:
(map + (circular-list val) lst)
For example:
(map + (circular-list 10) (list 0 1 2 3 4 5))
returns:
(10 11 12 13 14 15)
Of course, you could do this by replacing + with (lambda (x) (+ x val)), but sometimes the above idiom can be handier. Note that this only works with the srfi-1 version of map, which can accept lists of different sizes.