I have this since I coded mostly code snippets so far... By my own code
fails on the "elegant" requirement, I fear.
> 2. Purely Scala (but if someone wants to throw a Scalaz snippet. I
> wouldn't be interested, but someone else would)
> 3. Something that can bring value to other Scala programmers. (I know,
> it flies in the face of the definition of occult)
> 4. Maybe something obscure that Scala already has that most of the
> public doesn't know.
This last part is... obscure. It depends on what "most of the public"
is. I am probably part of most of the public, but then lot of Scala is
still obscure for me...
For example, I recently discovered a feature of Scala that I didn't know
(then again, I still have to read fully the base books on Scala), the
map(2*) syntax.
I saw this form in a cheat sheet, but I saw it in action in a compact
and elegant code from Daniel Sobral:
def
f(s:Seq[_]):String=if(s.isEmpty)""else{val(l,r)=s.span(s.head==);l.size+" "+s.head+"
"+f(r)}
readLine
println(f(readLine split' '))
Can be seen in context at:
http://codegolf.stackexchange.com/questions/1015/run-length-encoding
There is also the code from Martin Odersky, from Devoxx 2010 (message in
this mailing list of 2011-07-28, thread "Martin Odersky's devoxx 2010
talk. phonecode" which I find elegant and short, although not obscure.
Perhaps the usage of string as a collection of characters is nice enough
to be in your collection.
I made a probably less elegant but slightly closer of the original
proposal (skipping single numbers; able to use the old number codes),
which can be found at:
http://bazaar.launchpad.net/~philho/+junk/Scala/view/head:/_QuickExperiments/PhoneMnemonics.scala
Good stuff from Martin, bugs and ugly stuff from me...
A bit longer than your needs, but then again, I use formatting rules
that aren't afraid of using vertical space... :-)
Near the end of my Frankenstein monster
http://bazaar.launchpad.net/~philho/+junk/Scala/view/head:/Base.scala I
collected some cool code snippets (from mailing lists and other sources)
that might interest you.
--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --
I don't know if this qualifies as obscure or not, but:
(n: Int) => (2 to n) |> (r => r.foldLeft(r.toSet)((ps, x) => if
(ps(x)) ps -- (x * x to n by x) else ps))
It requires |>, which is available on Scalaz and other utility libraries.
This one uses something that always surprises people about regex:
val varPattern = """\$\{([^}]*)}""".r
def template(text: String, vars: Map[String, String]) = varPattern
replaceSomeIn (text, m => vars get (m group 1))
--
Daniel C. Sobral
I travel to the future all the time.
> Near the end of my Frankenstein monster
> http://bazaar.launchpad.net/~philho/+junk/Scala/view/head:/Base.scala
> I collected some cool code snippets (from mailing lists and other
> sources) that might interest you.
The "eachWithIndex" example can be done with the standard collection
method zipWithIndex:
Vector.fill(20)(math.random).zipWithIndex.foreach{
case (num, idx) => println("At " + idx + ": " + num)}
--
Jim
Actually, one doesn't need the 'lazy' here, because Stream itself is lazy.
Laziness provides better termination guarantees.
- --
Tony Morris
http://tmorris.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJOQbrWAAoJEPxHMY3rBz0PTj4IAJFTal7oVWL76QxCwgFP+8cp
xNk5SuCzd9PBjqDVaoVQ0l0NArK4gWOjkXNEmI1SNcc3eANcsdxH1q4i2GU6Xnel
gTBukyHE5kGDFa3WsBnDx0FqxFlFe/0vQT3LK2hf7bfjz0+so+ycjiKb3purbU9V
aK/dH9EVLAZH0zNQ1VLx+ull1z7xLaSl+9Vlf2islgUqX0KBgFFv84lLW6/PZLbh
VsMZZuKSqFM1ZAoZhsRJpmks95PMgW+J40c3ujbIGTFyYP4tPuiKGg22ZHyiICNw
LBEaGks91ymp8qRC1WaEr13kC4adu9QElNo2ySGgy2hHYqPOVbKJ7ou5QcbmTZU=
=hZan
-----END PGP SIGNATURE-----
fib is a stream composed of 1, 1, and the stream resulting from a
computation. Since Stream is lazy, this computation is performed
on-demand.
The computation is fib itself paired with fib minus its first element,
and then both added together. The first element is fib(0) + fib(1),
that is, 2. The second element is fib(1) + fib(2) -- fib(2) is what we
have just computed: 2. So that's 1 + 2 == 3. Third element is fib(2) +
fib(3), which are the first two elements of this computation: 2 and 3.
And so on and on. But, remember, each element is computed *only* on
demand, because Stream's tail is non-strict.
How is that occult??
Is occult synonymous with concise?
RRS
Thanks, added to the monster...
I suppose one of the interests of the snippet, for me, was the example
of usage of implicit, but giving a standard alternative is still good. ^_^
Another point was that while loops are slightly faster than for loops or
collection iteration. The code snippet was probably about finding faster
alternatives to for (i <- 0 until n)
I just tested with Caliper out of curiosity, the eachWithIndex is
slightly faster than zipWithIndex, around 8% faster in 2.8.1.final, 9%
in 2.9.0.final (ie. slower collection; untested in latest RC).
For me, it complies to #3 (brings value to me that hasn't seen it
before; value enhanced by good explanation of Daniel) and somehow to #4
(I don't know well the streams; good point is that I had to look at the
ScalaDoc to see how to use this fib value).
And indeed, it might look obscure to an average Java programmer. That's
the kind of code that can be seen as seductive or repulsive by the
non-initiated...
I think the "occult" term must be taken with a grain of salt...
Occultness, Demonstrandum Est!
-------- Original-Nachricht --------
> Datum: Wed, 10 Aug 2011 10:47:21 -0400
> Von: "Razvan Cojocaru" <p...@razie.com>
> An: "\'Lucas Torri\'" <lucas...@gmail.com>, "\'Josh Suereth\'" <joshua....@gmail.com>
> CC: scala...@googlegroups.com
> Betreff: RE: [scala-user] Anyone have some good Scala Occult Code?
Ok, that was clever. :-) I always wanted to use tails or inits, but
never saw a place to fit it. :-)
The above did not produce what I was expecting. Perhaps you meant this:
def splits[A](as: Seq[A]): Seq[(Seq[A], Seq[A])] =
(as.inits.toSeq zip as.tails.toSeq.reverse).tail.init
--
Jim
On 11/08/11 04:11, Runar Bjarnason wrote:
> def allPairs[A](as: Seq[A]): Seq[(A, A)] =
> as.tails.toSeq.tail flatMap (as.zip(_))
>
>
Fun exercise related to recent themes.
The code above contains duplication. Specifically, the "as." part. This
can be removed with the introduction of an applicative functor instance.
Hint: S
- --
Tony Morris
http://tmorris.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJOQyZSAAoJEPxHMY3rBz0Pq7cH/35iAD+fkwM9gTOGcaGEySii
UN/ukIJrgZw7N2bXiupKsa1Q5zsURzG1h6wTI8HQqZC6RwcLUJEOPHI/2t5vns5E
9GgYJNQnnZM7wH9qlTGBWsZXxbcSaglp3PZqudrUlI2Ybd/gJ53Cr610vMQJ3aH1
So8+q94hgmXBUN0OOgNobQ7VIRfMWRxxeIfSFGfhxB8oqw0HxVN4qg366P8A86/+
jOKs2s40UxB8vfmrw58y9awdtSLlpYGTD+zNZHakC9vpTS4l/L1rzYlX/RExy86O
NJ6HUfexhA+rGhyU046FLV77lUagNYiwdEzhmumxo39f4UG7kGvU0S7/oFTwEIg=
=9aOM
-----END PGP SIGNATURE-----
Oroboros
RRS
Case study/essay
Let us examine this piece of code:
fib.zip(fib.tail)
Let us rename the identifiers to remove ourselves from the specific
problem at hand:
x.f(x.g)
Let us now remove the instance methods f and g, and assume they are
regular object functions, for no other reason than for the simplicity of
explanation:
f(x)(g(x))
What would be the most general type of such an expression assuming f, g
and x are free variables? That is to say, what is the type of this:
f => g => x => f(x)(g(x))
We can at least see that f is of the form ? => ? => ? while g is ? => ?
and x is ? but what types are represented by these question marks?
Given g: ? => ? then we know that its first argument is the same type as
the first argument to f and the same type as x itself. Let's call this
type X. So now we have:
f: X => ? => ?
g: X => ?
x: X
We now see that whatever f takes in its second argument is the same type
as the return type of g. Let's call this Y.
So now:
f: X => Y => ?
g: X => Y
x: X
The return of f is the same type as the entire expression. Let's call
that Z. So we have the expression:
f => g => x => f(x)(g(x))
has the type:
(X => Y => Z) => (X => Y) => X => Z
Let us now abstract on this type. Wherever X => appears, I will replace
it with F. So, for example, if X => Y will become F[Y]. To use a
different syntax, wherever I see Function1[X, Whatever], I will replace
it with F[Whatever]. Here goes:
F[Y => Z] => F[Y] => F[Z]
Look familiar?
What is the type of this expression:
f => a => for {
ff <- f
aa <- a
} yield ff(aa)
It has this type:
F[Y => Z] => F[Y] => F[Z]
(such that F has flatMap+map methods)
It's an applicative functor!
So if we suppose this function existed as, let's say, a method on F[Y =>
Z] with the name <*>, then we could write the original expression:
zip <*> tail
How handy is that!
The signature of F[Y => Z] => F[Y] => F[Z] has many possible values for
F, as you might know. There are many different values that satisfy the
constraint, "has flatMap+map methods" -- List, Option, Parser, etc. etc.
In our case, we have Function1[T, _], which is missing its flatMap
method in the standard libraries and has a map method but its name is
compose instead (take a close look at its type -- it is map in
disguise!). This special case of <*> to Function1[T, _] has special
significance in that it is the S combinator of the SKI combinator
calculus. Take a look http://en.wikipedia.org/wiki/SKI_combinator_calculus
Hope this helps.
- --
Tony Morris
http://tmorris.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJOQ46OAAoJEPxHMY3rBz0PsIUH+wZG1Bs4csrDbAt1ezGaW/Ns
M6Ae93xKHihvkGnpr7TKtc30HuCzhosDVOZbOyFR67tsoOfVieRmN9qyCeSk8G1n
KXqjNZX8yAGz4JdwvuLpghizOtfax1MTaaqZTDsXH+vCWLJpSXShjNoV8MW0yt4u
43maM9JYPa+tQib7OufmJ192P8SfWUYdTyys8tRaU0BhKbw0PRL2MA9hpRsUvE5w
YJRr4feBujaiduixuLV7b/exnJZbmc3lRy5wQDDzuBt0QCRDXEIF1kyEX9SZoyJy
7YwFtGiI0Bu2Qsb0gpvrar+hx0gQmF1Zd90VKJzediII+6gUffJvvQ1UmaZyFVc=
=bvwI
-----END PGP SIGNATURE-----
-------- Original-Nachricht --------
> Datum: Thu, 11 Aug 2011 18:10:54 +1000
> Von: Tony Morris <tonym...@gmail.com>
> An: scala...@googlegroups.com
> Betreff: Re: [scala-user] Anyone have some good Scala Occult Code?
-------- Original-Nachricht --------
> Datum: Thu, 11 Aug 2011 18:10:54 +1000
> Von: Tony Morris <tonym...@gmail.com>
> An: scala...@googlegroups.com
> Betreff: Re: [scala-user] Anyone have some good Scala Occult Code?
> -----BEGIN PGP SIGNED MESSAGE-----
Or rather, to be clearer...I understand what the code is doing with one exception:In the code: lazy val fib: Stream[Int] = 1 #:: 1 #:: fib.zip(fib.tail).map { case (a,b) => a+b }Where does the first Stream come from?I see that #:: is a helper method on the ConsWrapper class inside Stream and I understand thezip and tail interaction and I get that map uses the case statement given to generate the next fib.I'm just a teensy unclear as to where the very 1st Stream comes from other than having a notionthat it's more of a promise of a stream inferred from the type of fib than an actual Stream...
from there, i can usually get the general idea easily
(i'm not the abstract math type - i prefer to see things working)
-------- Original-Nachricht --------
> Datum: Thu, 11 Aug 2011 10:50:14 +0200
> Von: Adam Jorgensen <adam.jor...@gmail.com>
> An: scala...@googlegroups.com
> Betreff: Re: [scala-user] Anyone have some good Scala Occult Code?
> Thanks for trying, but I fear you've confused me even more...
-------- Original-Nachricht --------
> Datum: Thu, 11 Aug 2011 10:55:20 +0200
> Von: Adam Jorgensen <adam.jor...@gmail.com>
> An: scala...@googlegroups.com
> Betreff: Re: [scala-user] Anyone have some good Scala Occult Code?
> Or rather, to be clearer...
it's like
def x:Int = x+1, just lazy. there is no "first x"
-------- Original-Nachricht --------
> Datum: Thu, 11 Aug 2011 11:19:51 +0200
> Von: "Dennis Haupt" <h-s...@gmx.de>
> An: Adam Jorgensen <adam.jor...@gmail.com>, scala...@googlegroups.com
In Scalaz, at least,
tail <*> zip
Which has always struck me as being in the wrong order. That's to help
type inference along right?
On 11/08/11 22:37, Daniel Sobral wrote:
> In Scalaz, at least,
>
> tail <*> zip
>
> Which has always struck me as being in the wrong order. That's to help
> type inference along right?
Well, map is around the wrong way too, so we simply read it all right to
left with some annoying parentheses.
z <*> (y <*> (x map f))
- --
Tony Morris
http://tmorris.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJORQZNAAoJEPxHMY3rBz0P8+cH/2mlAcXlZrQH3Q+Aop28XnuI
FSQOtY0Y9LEayFOv5PCcNKG1SQkzeTWS0VGIup9iex/xLcbJfGovPYA0rPLGAHuv
k6e+Xw63QELmpI7VhDr33udtV5+ZYrU7QffYC2UV3No3oq8LVRsQHVZJnz6C4+Kn
yzggHTweik0ramQluruhgrIOBnhdrubGsuZKDc4QlF2kVK9SrbyXAIdtNgA8HeuF
HRQD/cudzmZwlYZPOd4sU1zbQ9THk3ByyneHFIhkj1kkqY5ZjFjB9/s4koq7x8GI
un+c4dh3veB2NzxzAQ0AIMu379lFANR495xwnw/7YeWO0BAuEIxNaM2g5G1P390=
=1gtR
-----END PGP SIGNATURE-----