Remove the first char to extract an integer (unhandled exception: Subscript) - algorithm

I'm trying to write a function which extracts only the integer in a string.
All my strings have the format Ci where C is a single character and i is an integer. I would like to be able to remove the C from my string.
I tried something like this :
fun transformKripke x =
if size x > 1
then String.substring (x, 1, size x)
else x
But unfortunately, I get an error like unhandled exception: Subscript.
I assume it's because sometimes my string will be empty and size of empty string is not working. But I don't know how to make it work... :/
Thanks in advance for your help
Best Regards.

The problem is calling String.substring (x, 1, size x) when x is not long enough.
The following should fix your immediate problem:
fun transformKripke s =
if size s = 0
then s
else String.substring (s, 1, size s)
or slightly prettier:
fun transformKripke s =
if size s = 0
then s
else String.extract (s, 1, NONE) (* means "until the end" *)
But you may want to consider naming your function something more general so that it can be useful in more senses than performing a Kripke transform (whatever that is). For example, you may want to be able to extract an actual int the first time one occurs anywhere in a string, regardless of how many non-integer characters that precede it:
fun extractInt s =
let val len = String.size s
fun helper pos result =
if pos = len
then result
else let val c = String.sub (s, pos)
val d = ord c - ord #"0"
in case (Char.isDigit c, result) of
(true, NONE) => helper (pos+1) (SOME d)
| (true, SOME ds) => helper (pos+1) (SOME (ds * 10 + d))
| (false, NONE) => helper (pos+1) NONE
| (false, SOME ds) => SOME ds
end
in helper 0 NONE
end

My mistake was stupid,
The string is finishing at size x -1 not size x. So now it's correct :
fun transformKripke x =
if size x > 1
then String.substring (x, 1, (size x)-1)
else x
Hope it will help ! :)

Related

Given: aabcdddeabb => Expected: [(a,2),(b,1),(c,1),(d,3),(e,1),(a,1),(b,1)] in Scala

I'm really interested in how this algorithm can be implemented. If possible, it would be great to see an implementation with and without recursion. I am new to the language so I would be very grateful for help. All I could come up with was this code and it goes no further:
print(counterOccur("aabcdddeabb"))
def counterOccur(string: String) =
string.toCharArray.toList.map(char => {
if (!char.charValue().equals(char.charValue() + 1)) (char, counter)
else (char, counter + 1)
})
I realize that it's not even close to the truth, I just don't even have a clue what else could be used.
First solution with using recursion. I take Char by Char from string and check if last element in the Vector is the same as current. If elements the same I update last element by increasing count(It is first case). If last element does not the same I just add new element to the Vector(second case). When I took all Chars from the string I just return result.
def counterOccur(string: String): Vector[(Char, Int)] = {
#tailrec
def loop(str: List[Char], result: Vector[(Char, Int)]): Vector[(Char, Int)] = {
str match {
case x :: xs if result.lastOption.exists(_._1.equals(x)) =>
val count = result(result.size - 1)._2
loop(xs, result.updated(result.size - 1, (x, count + 1)))
case x :: xs =>
loop(xs, result :+ (x, 1))
case Nil => result
}
}
loop(string.toList, Vector.empty[(Char, Int)])
}
println(counterOccur("aabcdddeabb"))
Second solution that does not use recursion. It works the same, but instead of the recursion it is using foldLeft.
def counterOccur2(string: String): Vector[(Char, Int)] = {
string.foldLeft(Vector.empty[(Char, Int)])((r, v) => {
val lastElementIndex = r.size - 1
if (r.lastOption.exists(lv => lv._1.equals(v))) {
r.updated(lastElementIndex, (v, r(lastElementIndex)._2 + 1))
} else {
r :+ (v, 1)
}
})
}
println(counterOccur2("aabcdddeabb"))
You can use a very simple foldLeft to accumulate. You also don't need toCharArray and toList because strings are implicitly convertible to Seq[Char]:
"aabcdddeabb".foldLeft(collection.mutable.ListBuffer[(Char,Int)]()){ (acc, elm) =>
acc.lastOption match {
case Some((c, i)) if c == elm =>
acc.dropRightInPlace(1).addOne((elm, i+1))
case _ =>
acc.addOne((elm, 1))
}
}
Here is a solution using foldLeft and a custom State case class:
def countConsecutives[A](data: List[A]): List[(A, Int)] = {
final case class State(currentElem: A, currentCount: Int, acc: List[(A, Int)]) {
def result: List[(A, Int)] =
((currentElem -> currentCount) :: acc).reverse
def nextState(newElem: A): State =
if (newElem == currentElem)
this.copy(currentCount = this.currentCount + 1)
else
State(
currentElem = newElem,
currentCount = 1,
acc = (this.currentElem -> this.currentCount) :: this.acc
)
}
object State {
def initial(a: A): State =
State(
currentElem = a,
currentCount = 1,
acc = List.empty
)
}
data match {
case a :: tail =>
tail.foldLeft(State.initial(a)) {
case (state, newElem) =>
state.nextState(newElem)
}.result
case Nil =>
List.empty
}
}
You can see the code running here.
One possibility is to use the unfold method. This method is defined for several collection types, here I'm using it to produce an Iterator (documented here for version 2.13.8):
def spans[A](as: Seq[A]): Iterator[Seq[A]] =
Iterator.unfold(as) {
case head +: tail =>
val (span, rest) = tail.span(_ == head)
Some((head +: span, rest))
case _ =>
None
}
unfold starts from a state and applies a function that returns, either:
None if we want to signal that the collection ended
Some of a pair that contains the next item of the collection we want to produce and the "remaining" state that will be fed to the next iteration.
In this example in particular, we start from a sequence of A called as (which can be a sequence of characters) and at each iteration:
if there's at least one item
we split head and tail
we further split the tail into the longest prefix that contains items equal to the head and the rest
we return the head and the prefix we got above as the next item
we return the rest of the collection as the state for the following iteration
otherwise, we return None as there's nothing more to be done
The result is a fairly flexible function that can be used to group together spans of equal items. You can then define the function you wanted initially in terms of this:
def spanLengths[A](as: Seq[A]): Iterator[(A, Int)] =
spans(as).map(a => a.head -> a.length)
This can be probably made more generic and its performance improved, but I hope this can be an helpful example about another possible approach. While folding a collection is a recursive approach, unfolding is referred to as a corecursive one (Wikipedia article).
You can play around with this code here on Scastie.
For
str = "aabcdddeabb"
you could extract matches of the regular expression
rgx = /(.)\1*/
to obtain the array
["aa", "b", "c", "ddd", "e", "a", "bb"]
and then map each element of the array to the desired string.1
def counterOccur(str: String): List[(Char, Int)] = {
"""(.)\1*""".r
.findAllIn(str)
.map(m => (m.charAt(0), m.length)).toList
}
counterOccur("aabcdddeabb")
#=> res0: List[(Char, Int)] = List((a,2), (b,1), (c,1), (d,3), (e,1), (a,1), (b,2))
The regular expression reads, "match any character and save it to capture group 1 ((.)), then match the content of capture group 1 zero or more times (\1*).
1. Scala code kindly provided by #Thefourthbird.

Algorithm to check matching parenthesis

This relates to the Coursera Scala course so I want to directly ask you NOT to give me the answer to the problem, but rather to help me debug why something is happening, as a direct answer would violate the Coursera honor code.
I have the following code:
def balance(chars: List[Char]): Boolean = {
val x = 0
def loop(list: List[Char]): Boolean = {
println(list)
if (list.isEmpty) if(x == 0) true
else if (list.head == '(') pushToStack(list.tail)
else if (list.head == ')') if(x <= 0) false else decreaseStack(list.tail)
else loop(list.tail)
true
}
def pushToStack(myList: List[Char]) { x + 1; loop(myList)}
def decreaseStack(myList: List[Char]) { x - 1; loop(myList)}
loop(chars)
}
A simple explanation:
If the code sees a "(" then it adds 1 to a variable. If it sees a ")" then it first checks whether the variable is equal to or smaller than 0. If this is the case, it returns false. If the value is bigger than 0 then it simply decreases one from the variable.
I have tried running the following:
if(balance("This is surely bad :-( ) (".toList)) println("balanced") else println("not balanced");
Clearly this is not balanced, but my code is returning balanced.
Again: I am not asking for help in writing this program, but rather help in explained why the code is returning "balanced" when clearly the string is not balanced
--EDIT--
def balance(chars: List[Char]): Boolean = {
val temp = 0;
def loop(list: List[Char], number: Int): Boolean = {
println(list)
if (list.isEmpty) if(number == 0) true
else if (list.head == '(') loop(list.tail, number + 1)
else if (list.head == ')') if(number <= 0) false else loop(list.tail, number - 1)
else loop(list.tail,number)
true
}
loop(chars,0)
}
^^ Still prints out balanced
You are using an immutable x when you really want a mutable x.
Here, let me rewrite it for you in a tail recursive style to show you what you're actually doing:
#tailrec def loop(myList: List[Char], cur: Int = 0): Boolean = myList match{
case "(" :: xs =>
val tempINeverUse = cur+1
loop(xs, cur) //I passed in 0 without ever changing "cur"!
case ")" :: xs if cur < 0 => false //This is a bug, regardless if you fix the rest of it
case ")" :: xs =>
val tempINeverUse = cur-1
loop(xs, cur) //Passed in 0 again!
case x :: xs => loop(xs, cur)
case Nil => cur == 0 //Since I've never changed it, it will be 0.
}
You need to keep a context of parenthesis in comments or in quotes as well. You can use a counter to achieve that. If the counter is set for a comment or a double quote then ignore any parenthesis that comes your way. Reset the counter whenever you find a finishing comment or double quote

How does Scala's .min avoid the penalty of boxing and unboxing?

Vector.min is implemented as
def min[B >: A](implicit cmp: Ordering[B]): A = {
if (isEmpty)
throw new UnsupportedOperationException("empty.min")
reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y)
}
and when you profile
Vector.fill(1000000)(scala.util.Random.nextLong).min
it's fast and there's no boxing or unboxing going on. If, however, you write the apparently equivalent
val cmp = implicitly[Ordering[Long]]
Vector.fill(1000000)(scala.util.Random.nextLong).reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y)
it runs approximately 10 times slower (ignoring the time in Random, which otherwise dominates this, and yes, I warmed my benchmarks up...).
How is the first version avoiding the performance penalty of the boxing?
Edit: here's my profiling code:
val cmp = implicitly[Ordering[Long]]
def randomLongs = Vector.fill(1000000)(scala.util.Random.nextLong)
def timing[R](f: => R): (Long, R) = {
val startTime = System.nanoTime
val result = f
((System.nanoTime - startTime) / 1000000, result)
}
def minTiming = { val r = randomLongs; timing(r.min)._1 }
def reduceLeftTiming = { val r = randomLongs; timing(r.reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y))._1 }
while(true) {
println((minTiming, reduceLeftTiming))
}
and I see times using min of around 20ms, using reduceLeft of ~200ms. I've profiled this code using YourKit; here's a screen grab of the call tree showing that min doesn't result in any boxing.
I think the first version infers java.lang.Long for B. So there still is boxing going on, but only while filling the vector, and afterwards all comparisons are between boxed objects.
In the second version, since type of cmp is given as Ordering[Long], java.lang.Longs in the vector have to be unboxed before being passed to cmp.lteq(x, y).

Scalaz : validating in a for-comprehension and logging

I admit that the title is not very explicit : sorry for that.
Assume I have a for-comprehension :
for {v1<-Validation1(input)
v2<-Validation2(v1)
v3<-Validation3(v2)
} yield result
Validation1, Validation2 and Validation3 do some checking (e.g "age > 18") and use fail/success ; so if something is wrong, the for-comprehension aborts and I get the reason in the failure part of the result, else I get the expected value in the success part. So far, so good and nothing very difficult.
But Validation1, Validation2, Validation3 are successfull if their input satisfies some rules (e.g : "the guy can vote because his age is greater than 18 and his nationality is French") . what I want is to keep trace of the rules that are applied in order to be able to display them at the end.
It's clearly a use case of logging. but I hesitate on the way to do it :
Have an object "logger" that is accessible by any function (Validation1, 2 and 3 but also the caller that wants to display the content of the log)
Make the logger a parameter of Validation1, 2 and 3
Wait for the pertinent chapter of "Functional programming in Scala" :)
Other?
Thank for your advices
Edited on april 10
So, suppose I want to compute the function : x -> 1/sqrt(x)
First, I compute sqrt(x) by checking that x > 0 and then I take the inverse if not zero.
with scalaz.Validation, it is simple :
val failsquareroot= "Can't take squareroot of negative number"
val successsquareroot= "Squareroot ok"
val failinverse="Can't take inverse of zero"
val successinverse= "Inverse ok"
def squareroot(x:Double)=if (x < 0) failsquareroot.fail else sqrt(x).success
def inverse(x:Double)= if (x == 0) failinverse.fail else (1/x).success
def resultat(x:Double)= for {
y <- squareroot(x)
z<-inverse(y)
} yield z
Now, if squareroot successes, I want to log the string successsquaretoot and if inverse sucesses, I want to log the string successinverse so that the function resultat accumulates the both strings in case of success
I started with ValidationT as Yo Eight suggested :
def squareroot2(x:Double)=ValidationT[({type f[x] = Writer[String,x]})#f, String,Double](Writer(successsquareroot,squareroot(x)))
def inverse2(x:Double)=ValidationT[({type f[x] = Writer[String,x]})#f, String,Double](Writer(successinverse,inverse(x)))
But I can't find how to combine them in a for-comprehension.
Furthermore, to get the result of one of them, I have to write :
squareroot2(4).run.run
which seems strange
and in the way I wrote it, even in case of failure the strings successsquareroot is logged :
println(squareroot2(-1).run.run)
prints : (Squareroot ok,Failure(Can't take squareroot of negative number))
Thank you!
Benoit
Edited on april 12
So Yo Eight suggested this snippet :
def squareroot(x:Double) = if (x < 0) failureT("Can't take squareroot of negative number") else successT(sqrt(x))
def inverse(x:Double) = if (x == 0) failureT("Can't take inverse of zero ") else successT(1/x)
for {
y <- squareroot(x).flatMapF(i => Writer("Squareroot ok", i))
z <- inverse(y).flatMapF(i => Writer("Inverse ok", i))
} yield z
and he warned me that some type annotations was necessary. Effectivly, the return tpye of squareroot and inverse is rather ugly : it's a ValidationT of something that I had difficulties to understand!
So, I had to specify the return type explictly : def inverse(x:Double) : ValidationT[?,E,A] where "E" is String and "A" is Double (that was easy!). But what about the first one? It must be a monad (as far as I understand) and I choosed the simpliest : Id (that is Identity).
So now we have :
def squareroot(x:Double):ValidationT[Id,String,Double]=if (x < 0) failureT(failsquareroot) else successT(sqrt(x))
def inverse(x:Double):ValidationT[Id,String,Double]=if (x == 0) failureT(failinverse)else successT(1/x)
But the for-comprehension doesn't compile because "y" is not a Double but a WriterT[Id, String, Double]
Furthermore, the first logged message ("Squareroot ok") is "lost".
Eventually, I did like that :
def resultat(x:Double) = for {
y <- squareroot(x).flatMapF(i => Writer("Squareroot ok", i))
z <- inverse(y.run._2).flatMapF(i => Writer(y.run._1 + ", Inverse ok", i))
} yield z.run //Note that writing "z.run.run" doesn't compile
println("0 : " + resultat(0.0).run)
println("-1 : " +resultat(-1.0).run)
println("4 : " + resultat(4).run)
which gives :
0 : Failure(Can't take inverse of zero)
-1 : Failure(Can't take squareroot of negative number)
4 : Success((Squareroot ok, Inverse ok,0.5)
Cool! I would be better to use a List[String] for the Writer, but I think that I'm on the good way!
And now, I can think to my holidays (tomorrow!) :)
Edited on may 14
well, the code doesn't compile, but the error is in Yo Eight's last suggestion (Note that it is not an offense again Yo Eight who is a model of kindness!) . I submit you the full code and the error :
import scala.math._
import scalaz._
import Scalaz._
object validlog extends ValidationTFunctions {
val failsquareroot= "Can't take squareroot of negative number"
val successsquareroot= "Squareroot ok"
val failinverse="Can't take inverse of zero"
val successinverse= "Inverse ok"
case class MyId[A]( v: A)
implicit val myIdPointed = new Pointed[MyId]{
def point[A](v: => A) = MyId(v)
}
implicit def unId[A](my: MyId[A]): A = my.v
def squareroot(x:Double):ValidationT[({type f[x] = WriterT[MyId,String, x]})#f,String,Double]=if (x < 0) failureT[({type f[x] = WriterT[MyId,String, x]})#f,String,Double](failsquareroot) else successT[({type f[x] = WriterT[MyId,String, x]})#f,String,Double](sqrt(x))
def inverse(x:Double):ValidationT[({type f[x] = WriterT[MyId, String, x]})#f,String,Double]=if (x == 0) failureT[({type f[x] = WriterT[MyId,String, x]})#f,String,Double](failinverse) else successT[({type f[x] = WriterT[MyId,String, x]})#f,String,Double](1/x)
/* def resultat(x:Double) = for {
y <- squareroot(x).flatMapF(i => Writer(", Squareroot ok", i))
z <- inverse(y).flatMapF(i => Writer(", Inverse ok", i))
} yield z */
def main(args: Array[String]): Unit = {
println(inverse(0.0).run)
println(inverse(0.5).run)
println(squareroot(-1.0).run)
println(inverse(4.0).run)
}
}
Here is the terminal's session :
benoit#benoit-laptop:~$ cd scala
benoit#benoit-laptop:~/scala$ scala -version
Scala code runner version 2.9.2 -- Copyright 2002-2011, LAMP/EPFL
benoit#benoit-laptop:~/scala$ scala -cp ./scalaz7/scalaz-core_2.9.2-7.0-SNAPSHOT.jar validlog.scala
/home/benoit/scala/validlog.scala:15: error: object creation impossible, since method map in trait Functor of type [A, B](fa: Main.MyId[A])(f: A => B)Main.MyId[B] is not defined
implicit val myIdPointed = new Pointed[MyId]{
^
one error found
I guess there is something that I've missed from the beginning that could explain why I'm sticked for some weeks!
Benoit
Edited on may 15
Compiling your code, I have a first error :
could not find implicit value for parameter F: scalaz.Pointed[Main.$anon.ValidationTExample.WriterAlias]
After some tries, I rewrote the import in this manner :
import scalaz.Writer
import scalaz.std.string._
import scalaz.Id._
import scalaz.WriterT
import scalaz.ValidationT
import scala.Math._
There is still one error :
error: could not find implicit value for parameter F: scalaz.Monad[[x]scalaz.WriterT[[+X]X,String,x]]
y <- squareroot(x).flatMapF(i => Writer("Squareroot ok", i))
^
one error found
This error was present with the code you wrote on may 14. Obviously, it is difficult to understand what to iimport exactly with scalaz-seven. Using the version 6, things looked simpler : one just had to import scalaz._ and Scalaz._
I feel like a "desperate housewriter" :) (yes, I agree, it is not very astute but it's relaxing!)
Benoit
May 23
Ouf! It effectively works with the last version of scalaz-seven : note that I had to build it instead of downloading a snapshot.
that's great!
For those who are interested, here is the output :
0 : (Squareroot ok,Failure(Can't take inverse of zero ))
-1 : (,Failure(Can't take squareroot of negative number))
4 : (Squareroot ok, Inverse ok,Success(0.5))
Yo Eight, if by chance we meet one day, i'll pay you a beer!
Benoit
In order to log during monadic computation, you have to use an instance of Writer monad. Since monad doesn't compose and you want to keep "Validation" effect, you should use a Validation Monad Transformer. I don't know which version of ScalaZ you're using but Scalaz7 (branch scalaz-seven) provides such monad transformer (namely ValidationT).
so we get:
ValidationT[({type f[x] = Writer[W, x]})#f, A]
with W the type of your logger
According to your edit, here's how I'll do it
def squareroot(x:Double) = if (x < 0) failureT("Can't take squareroot of negative number") else successT(sqrt(x))
def inverse(x:Double) = if (x == 0) failureT("Can't take inverse of zero ") else successT(1/x)
And now, how to use it in a for-comprehension
for {
y <- squareroot(x).flatMapF(i => Writer("Squareroot ok", i))
z <- inverse(y).flatMapF(i => Writer("Inverse ok", i))
} yield z
Those snippets might need more type annotations
Edited on april 13
Here's the correct type annotations for your methods:
def squareroot(x:Double):ValidationT[({type f[x] = Writer[String, x]})#f,String,Double]
def inverse(x:Double):ValidationT[{type f[x] = Writer[String, x]})#f,String,Double]
That way, you can define resultat method like this:
def resultat(x:Double) = for {
y <- squareroot(x).flatMapF(i => Writer(", Squareroot ok", i))
z <- inverse(y).flatMapF(i => Writer(", Inverse ok", i))
} yield z
You could also use List[String] as a log type because it's a monoid
BTW, I speak French if it can help :-)
Edit on May 14
The problem was: The compiler cannot resolve
implicitly[Pointed[({ type f[x] = Writer[String, x] })#f]]
because WriterT need an instance of Monoid[String] and Pointed[Id].
import std.string._ // this import all string functions and instances
import Id._ // this import all Id functions and instances
Here is the full executable code
import scalaz._
import std.string._
import Id._
import scalaz.WriterT
import scalaz.ValidationT
import scala.Math._
object ValidationTExample extends Application {
type ValidationTWriterAlias[W, A] = ValidationT[({type f[x] = Writer[W, x]})#f, W, A]
type WriterAlias[A] = Writer[String, A]
def squareroot(x:Double): ValidationTWriterAlias[String, Double] =
if (x < 0) ValidationT.failureT[WriterAlias, String, Double]("Can't take squareroot of negative number")
else ValidationT.successT[WriterAlias, String, Double](sqrt(x))
def inverse(x:Double): ValidationTWriterAlias[String, Double] =
if (x == 0) ValidationT.failureT[WriterAlias, String, Double]("Can't take inverse of zero ")
else ValidationT.successT[WriterAlias, String, Double](1/x)
def resultat(x:Double) = for {
y <- squareroot(x).flatMapF(i => Writer("Squareroot ok", i))
z <- inverse(y).flatMapF(i => Writer(", Inverse ok", i))
} yield z
println("0 : " + resultat(0.0).run.run)
println("-1 : " + resultat(-1.0).run.run)
println("4 : " + resultat(4).run.run)
}
Edit on August 14
This code is no longer valid in scalaz-seven. ValidationT has been removed since Validation is not a monad. Hopefully, EitherT can be used instead. Besides, a new MonadWriter/ListenableMonadWriter typeclass has been added to alleviate those type annotations.
import scalaz._
import std.string._
import syntax.monadwriter._
import scala.Math._
object EitherTExample extends Application {
implicit val monadWriter = EitherT.monadWriter[Writer, String, String]
def squareroot(x: Double) =
if (x < 0)
monadWriter.left[Double]("Can't take squareroot of negative number")
else
monadWriter.right[Double](sqrt(x))
def inverse(x: Double) =
if (x == 0)
monadWriter.left[Double]("Can't take inverse of zero")
else
monadWriter.right[Double](1 / x)
def resultat(x: Double) = for {
y <- squareroot(x) :++> "Squareroot ok"
z <- inverse(y) :++> ", Inverse ok"
} yield z
println("0 : " + resultat(0.0).run.run)
println("-1 : " + resultat(-1.0).run.run)
println("4 : " + resultat(4).run.run)
}

How do I translate this Haskell to F#?

I'm trying to learn F# by translating some Haskell code I wrote a very long time ago, but I'm stuck!
percent :: Int -> Int -> Float
percent a b = (fromInt a / fromInt b) * 100
freqs :: String -> [Float]
freqs ws = [percent (count x ws) (lowers ws) | x <- ['a' .. 'z']]
I've managed this:
let percent a b = (float a / float b) * 100.
although i dont like having to have the . after the 100.
What is the name of the operation I am performing in freqs, and how do I translate it to F#?
Edit: count and lowers are Char -> String -> Int and String -> Int respectively, and I have translated these already.
This is a list comprehension, and in F# it looks like the last two lines below:
// stub out since don't know the implementation
let count (c:char) (s:string) = 4
let lowers (s:string) = 10
// your code
let percent a b = (float a / float b) * 100.
let freq ws = [for x in ['a'..'z'] do
yield percent (count x ws) (lowers ws)]
More generally I think Haskell list comprehensions have the form suggested by the example below, and the corresponding F# is shown.
// Haskell
// [e(x,y) | x <- l1, y <- l2, pred(x,y)]
// F#
[for x in l1 do
for y in l2 do
if pred(x,y) then
yield e(x,y)]
Note that Brian's F# code:
let freq ws = [for x in ['a'..'z'] do yield percent (count x ws) (lowers ws)]
Can be written more elegantly as:
let freq ws = [for x in 'a'..'z' -> percent (count x ws) (lowers ws)]

Resources