Eric Kolotyluk | 1 Feb 03:29
Picon
Gravatar

Re: Addicted to Pattern Matching

OK, I will just have to assume Simon is being sarcastic and really does 
love pattern matching.

I am so tired of the limitations of the C, C++, Java style switch 
statement. In C# I cannot believe how many times I switch on String 
cases - that small improvement is so incredibly useful. I am glad the 
Java is finally catching up in this regard, but both Java and C# are a 
far cry from Scala. Over the years I make much more use of switch in 
Java than when I used to rely more on chains of if-then-else (which can 
get really ugly).

It may be true there are bugs or other issues with pattern matching in 
Scala, but I have not encountered them enough (if at all) to find it a 
problem. I used the programming language SR over almost 20 years ago, 
and I really love how well pattern matching work on events, but I have 
not had a chance to do that sort of thing again until recently when 
working with Scala. Now that I have been writing production code in 
Scala, I just keep finding more an more situations where I can clean up 
my code using match/case. Now it is becoming instictive and I write the 
code first based on match/case instead of the result of refactoring.

When you think about it, one of the things the human brain is really 
good at is pattern matching. One of the reasons I keep stressing that 
there needs to be more good concrete examples of Scala code is that I 
can often look a well written piece of code and more easily infer what 
is going on than reading pages and pages of theory of how to write the 
code. Oddly enough, in the past I have often had trouble understanding 
people's example of pattern matching in Scala, but now that I have more 
experience with it I am finding those example easier to understand.

(Continue reading)

Eric Kolotyluk | 1 Feb 03:32
Picon
Gravatar

Re: Addicted to Pattern Matching - Array[String]

Does anyone have any good examples of how to use match/case with 
Array[String] - or is it just best to always convert Array[String] to 
List[String]?

Cheers, Eric

Eric Kolotyluk | 1 Feb 03:39
Picon
Gravatar

Re: Addicted to Pattern Matching - Error Results

One of the things I often do now is write functions that return a case 
class ReturnResult, with subclasses NormalResult and ErrorResult. Then I 
can write code like

    fn(foo) match {
      case NormalResult(blah) =>
      case ErrorResult(blah) = >

While in many cases it is best to throw an exception, often this 
return-result pattern works best for me, especially when I am 
'scripting' and error results are just as likely as normal results. When 
error results are less likely then I tend to prefer exceptions and try 
blocks.

Does anyone else have any opinions on this?

Cheers, Eric

sreque | 1 Feb 04:55
Picon
Favicon

Re: Addicted to Pattern Matching - Error Results

I think for this particular case, where a function can return either
of two values, people usually prefer using class Either or Scalaz's
Validation. That way, you don't have to create boilerplate case
classes each time you want to use this pattern. I actually took the
time to write an Either class in C#, which, even without pattern
matching or good ways of composing functions, has turned out to be
pretty handy. I still have a hard time structuring my programs
functionally with them or structuring all my code inside of a
Validation monad. For instance, In C#, the boiler plate required to
use the ValidationNEL applicative functor to accumulate errors is
pretty painful, especially as their is no type inference for Lambdas
except when passed as a function argument. Also, C#'s type inference
in general isn't nearly as good as Scala's, doesn't have a bottom
type, and, in 3.5, at least, doesn't have type variance to make life
easier. Even with all that, I still like using Eithers! :)

On Jan 31, 8:39 pm, Eric Kolotyluk <eric.koloty...@gmail.com> wrote:
> One of the things I often do now is write functions that return a case
> class ReturnResult, with subclasses NormalResult and ErrorResult. Then I
> can write code like
>
>     fn(foo) match {
>       case NormalResult(blah) =>
>       case ErrorResult(blah) = >
>
> While in many cases it is best to throw an exception, often this
> return-result pattern works best for me, especially when I am
> 'scripting' and error results are just as likely as normal results. When
> error results are less likely then I tend to prefer exceptions and try
> blocks.
(Continue reading)

Bernd Johannes | 1 Feb 07:36
Picon

Re: memoized functions / methods

Am Montag, 30. Januar 2012, 21:51:53 schrieb Dan Rosen:

> On Monday, January 30, 2012 12:31:39 PM UTC-8, Daniel Sobral wrote:

> > However, I think "lazy def" would make

> > perfect sense and not create a new keyword.

>

> The only beef I have with "lazy def" is that it doesn't hint at the fact

> that the function being defined is side effect free. I'd have suggested

> "pure def" actually, but I know that scalaz uses 'pure' as a method name,

> and it's called frequently from client code. And "idem def" just sounds

> goofy.

>

> Anyway, would love to hear your thoughts on implementation...

>

> dr


For what it's worth - I would prefer 'deterministic' (burrowed from various SQL dialects). That doesn't describe the fact that something is actually memoized but indicates that it COULD be memoized if the implementation decides to do so.


That opens up the freedom for the implementation to drop memoization at the cost of performance if the need arises (runtime architecture, memory consumption, solution space).


The actual memoization and all the possible behaviour of it could be delegated to a "global" memoization handler with one instance per thread (I don't assume that sharing the caches between multiple threads in a concurrent setup will perform well - but this could be customizable behaviour as well).


Global because this opens up the possibility to implement cache balancing mechanisms over several memoized functions (e.g. a global LRU dropout scheme or something balancing LRU and cost of calculation). From my experience it's not satisfactory to throw just a caching Map at a function when the solution space is non-trivial.


An application could replace the default handler (which e.g. could do simply nothing and all memoization interception code would silently be erased) with one that implements exact that memoization behaviour which is needed for this specific application.


The hard part is to be able to catch nondeterministic operations in the function body as good as possible. The first step would simply be to delegate it completely to the developer - deterministic would be a mere tag then without guarantees or enforced behaviour restrictions.


Just my 5 cents

Greetings Bernd

Seth Tisue | 1 Feb 07:46
Gravatar

Re: Re: Addicted to Pattern Matching - Array[String]

On Tue, Jan 31, 2012 at 8:32 PM, Eric Kolotyluk
<eric.kolotyluk <at> gmail.com> wrote:
> Does anyone have any good examples of how to use match/case with
> Array[String] - or is it just best to always convert Array[String] to
> List[String]?

What are you trying to do that doesn't work? Here's some simple things
that work:

Welcome to Scala version 2.9.1.final

scala> Array(1, 2, 3) match {
     | case Array(x, y, z) => (x, y, z)
     | }
res0: (Int, Int, Int) = (1,2,3)

scala> Array(4, 5, 6) match {
     | case Array(_, z @ _*) => z
     | }
res1: Seq[Int] = Vector(5, 6)

--

-- 
Seth Tisue | Northwestern University | http://tisue.net
lead developer, NetLogo: http://ccl.northwestern.edu/netlogo/

Daniel Sobral | 1 Feb 13:15
Picon
Gravatar

Re: Re: Addicted to Pattern Matching - Error Results

On Wed, Feb 1, 2012 at 00:39, Eric Kolotyluk <eric.kolotyluk <at> gmail.com> wrote:
> One of the things I often do now is write functions that return a case class
> ReturnResult, with subclasses NormalResult and ErrorResult. Then I can write
> code like
>
>   fn(foo) match {
>     case NormalResult(blah) =>
>     case ErrorResult(blah) = >
>
> While in many cases it is best to throw an exception, often this
> return-result pattern works best for me, especially when I am 'scripting'
> and error results are just as likely as normal results. When error results
> are less likely then I tend to prefer exceptions and try blocks.
>
> Does anyone else have any opinions on this?

That's Either, without type erasure. There's certainly an advantage to
not having type erasure, in particular Either's type parameters are
type constructors themselves. For example:

// works
(either: Either[String, Int]) match {
  case Right(n: Int) => // this is the "right" case, and we can reify n's type
  case Left(error: String) => // this is the exception case, and we
can reify error's type too
}

/ doesn't work
(either: Either[String, List[Int]]) match {
  case Left(list: List[_]) => // can't reify list's type
  case _ =>
}

So, while Either's pattern is nice, it's seriously constrained by type erasure.

Also, its methods make using it on for-comprehensions very awkward.
For an example of how to do it better, see Parsers.ParseResult, or, of
course, Scalaz Validation. While Validation is somewhat verbose, it's
definitely one of Scalaz gateway drugs.

--

-- 
Daniel C. Sobral

I travel to the future all the time.

Eric Kolotyluk | 1 Feb 19:56
Picon
Gravatar

Re: Re: Addicted to Pattern Matching - Array[String]

On 2012-01-31 10:46 PM, Seth Tisue wrote:
> On Tue, Jan 31, 2012 at 8:32 PM, Eric Kolotyluk
> <eric.kolotyluk <at> gmail.com>  wrote:
>> Does anyone have any good examples of how to use match/case with
>> Array[String] - or is it just best to always convert Array[String] to
>> List[String]?
> What are you trying to do that doesn't work? Here's some simple things
> that work:
>
> Welcome to Scala version 2.9.1.final
>
> scala>  Array(1, 2, 3) match {
>       | case Array(x, y, z) =>  (x, y, z)
>       | }
> res0: (Int, Int, Int) = (1,2,3)
>
> scala>  Array(4, 5, 6) match {
>       | case Array(_, z @ _*) =>  z
>       | }
> res1: Seq[Int] = Vector(5, 6)
>
I was trying to match a regex in one of the Array positions like

scala> val help = "help".r
help: scala.util.matching.Regex = help

scala> val c1 = Array("help")
c1: Array[java.lang.String] = Array(help)

scala> c1 match {
      | case Array(help(_)) => println("ok")
      | case _ => println("nope")
      | }
nope

Is there a way to capture the tail of the array too?

Cheers, Eric

Eric Kolotyluk | 1 Feb 20:05
Picon
Gravatar

Re: Re: Addicted to Pattern Matching - Error Results

On 2012-02-01 4:15 AM, Daniel Sobral wrote:
> On Wed, Feb 1, 2012 at 00:39, Eric Kolotyluk<eric.kolotyluk <at> gmail.com>  wrote:
>> One of the things I often do now is write functions that return a case class
>> ReturnResult, with subclasses NormalResult and ErrorResult. Then I can write
>> code like
>>
>>    fn(foo) match {
>>      case NormalResult(blah) =>
>>      case ErrorResult(blah) =>
>>
>> While in many cases it is best to throw an exception, often this
>> return-result pattern works best for me, especially when I am 'scripting'
>> and error results are just as likely as normal results. When error results
>> are less likely then I tend to prefer exceptions and try blocks.
>>
>> Does anyone else have any opinions on this?
> That's Either, without type erasure. There's certainly an advantage to
> not having type erasure, in particular Either's type parameters are
> type constructors themselves. For example:
>
> // works
> (either: Either[String, Int]) match {
>    case Right(n: Int) =>  // this is the "right" case, and we can reify n's type
>    case Left(error: String) =>  // this is the exception case, and we
> can reify error's type too
> }
>
>
> / doesn't work
> (either: Either[String, List[Int]]) match {
>    case Left(list: List[_]) =>  // can't reify list's type
>    case _ =>
> }
>
> So, while Either's pattern is nice, it's seriously constrained by type erasure.
>
> Also, its methods make using it on for-comprehensions very awkward.
> For an example of how to do it better, see Parsers.ParseResult, or, of
> course, Scalaz Validation. While Validation is somewhat verbose, it's
> definitely one of Scalaz gateway drugs.
>

Here is one common way I use Error Results

       val dropCommand = List("psql", "-U", "postgres", "-c", "DROP 
DATABASE " + database + ";")

       Run(dropCommand) match {
         case NormalResult(process, outLines, errLines) =>
           if (!errLines.isEmpty) {
             emit("psql errors:")
             emit(errLines)
           }
           if (!outLines.isEmpty) {
             emit("psql output:")
             emit(outLines)
           }
           return true
         case ErrorResult(process, outLines, errLines) =>
           emitError("psql exitValue = " + process.exitValue)
           if (!errLines.isEmpty) {
             emitError("psql errors:")
             emitError(errLines)
             // Succeed if the database does not exist
             if (errLines.contains("database \"" + database + "\" does 
not exist")) return true
           }
           if (!outLines.isEmpty) {
             emitError("psql output:")
             emitError(outLines)
           }
       }

While (I think) my code is fairly clear, it is more verbose than I would 
like. How would Either make this better?

Cheers, Eric

Ryan Hendrickson | 1 Feb 20:22
Favicon

RE: Re: Addicted to Pattern Matching - Array[String]

> I was trying to match a regex in one of the Array positions like
> 
> scala> val help = "help".r
> help: scala.util.matching.Regex = help
> 
> scala> val c1 = Array("help")
> c1: Array[java.lang.String] = Array(help)
> 
> scala> c1 match {
>       | case Array(help(_)) => println("ok")
>       | case _ => println("nope")
>       | }
> nope

The help regex doesn't have any capturing groups, which is why help(_) won't match anything. Try:

c1 match {
  case Array(help()) => println("ok")
}

----------------------------------------

This message is intended exclusively for the individual(s) or entity to
which it is addressed. It may contain information that is proprietary, 
privileged or confidential or otherwise legally exempt from disclosure. 
If you are not the named addressee, you are not authorized to read, 
print, retain, copy or disseminate this message or any part of it. 
If you have received this message in error, please notify the sender 
immediately by e-mail and delete all copies of the message.


Gmane