[scala] Option vs null

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

[scala] Option vs null

by Jim McBeath-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

As a vehicle for helping me learn Scala, I have converted one of my
Java programs over to Scala.  The Java code included a class with two
methods overloading the same name, one with an optional File argument
and the other with an optional String argument (representing a file
name).  The Java methods looked something like this:

    import java.io.File;
    public class Test {
        //f is optional, may be null
        public void foo(String s, File f) { }

        //name is optional may be null
        public void foo(String s, String name) { }
    }

As part of the conversion to Scala, I wanted to use Option objects
rather than using null to represent missing values.  After converting
to Scala, the above code looked something like this:

    import java.io.File
    class Test {
       
        def foo(s:String, fOpt:Option[File]):Unit = { }

        def foo(s:String, nameOpt:Option[String]):Unit = { }
    }

However, the compiler gives me the following error message:

    test.scala:6: error: double definition:
    method foo:(String,Option[String])Unit and
    method foo:(String,Option[java.io.File])Unit at line 4
    have same type after erasure: (java.lang.String,Option)Unit

Is there an elegant solution for this?  I could of course change the
names so as not to use overloading, or add an argument to one or the
other method to disambiguate.  I thought about trying to coalesce the
two methods into one, but I don't think I can declare an
"Option[String or File]" type, and changing it to Option[Any] would
weaken type-checking at caller sites.

At the moment I have reverted the overloaded methods back to their
original signature, accepting a nullable String or File rather than an
Option, but I am hoping there is a better "Scala way" solution.


There are a couple of small things that could be added to Scala
to make it a little simpler to interface to legacy Java code that
uses null as a marker for missing data.  In particular, it would be
convenient to have a "getOrNull" method on Option values when calling
into legacy Java code, and to have an easy way to create a None if
the raw value returned by legacy Java code is null, or a Some if
not null.  These two additions would make it a one-step operation
to convert each way between an Option value and a maybe-null value.
I have implemented these two changes in my code using the following
little object:

    object SomeOrNone {
        class OptionOrNull[T](x:Option[T]) {
            def getOrNull():T = if (x.isDefined) x.get else null.asInstanceOf[T]
        }

        implicit def optionOrNull[T](x:Option[T]) = new OptionOrNull(x)

        def apply[T](x:T) = if (x==null) None else Some(x)
    }

I then use "import SomeOrNone" and "import SomeOrNone.optionOrNull"
in the source files in which I want to be able to use the SomeOrNone
creation method or the getOrNull method on an Option.  In order to
simplify interfacing to legacy Java code, it would be nice to have the
standard Option class include the getOrNull method, and to add an
"orNone" constructor to the standard Some object so that I could say
"Some.orNone(x)", which would return a None if x were null, else
Some(x).

I was also a bit surprised to discover that Some(null) is legal.  I
thought the whole purpose of Option was not to have null values
floating around.  Perhaps there should also be a Some.notNull(x)
constructor that would throw an exception if x==null.

--
Jim

Re: [scala] Option vs null

by tmorris :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jim McBeath wrote:
| As a vehicle for helping me learn Scala, I have converted one of my
| Java programs over to Scala.  The Java code included a class with two
| methods overloading the same name, one with an optional File argument
| and the other with an optional String argument (representing a file
| name).  The Java methods looked something like this:
|
|     import java.io.File;
|     public class Test {
|         //f is optional, may be null
|         public void foo(String s, File f) { }
|
|         //name is optional may be null
|         public void foo(String s, String name) { }
|     }
|
| As part of the conversion to Scala, I wanted to use Option objects
| rather than using null to represent missing values.  After converting
| to Scala, the above code looked something like this:
|
|     import java.io.File
|     class Test {
|        
|         def foo(s:String, fOpt:Option[File]):Unit = { }
|
|         def foo(s:String, nameOpt:Option[String]):Unit = { }
|     }
|
| However, the compiler gives me the following error message:
|
|     test.scala:6: error: double definition:
|     method foo:(String,Option[String])Unit and
|     method foo:(String,Option[java.io.File])Unit at line 4
|     have same type after erasure: (java.lang.String,Option)Unit
|
| Is there an elegant solution for this?  I could of course change the
| names so as not to use overloading, or add an argument to one or the
| other method to disambiguate.  I thought about trying to coalesce the
| two methods into one, but I don't think I can declare an
| "Option[String or File]" type, and changing it to Option[Any] would
| weaken type-checking at caller sites.
Personally, I'd delete the String function and write a String -> File
implicit (if that is not to your liking, I'd abstract it in away such
that it does).

|
| At the moment I have reverted the overloaded methods back to their
| original signature, accepting a nullable String or File rather than an
| Option, but I am hoping there is a better "Scala way" solution.
|
|
| There are a couple of small things that could be added to Scala
| to make it a little simpler to interface to legacy Java code that
| uses null as a marker for missing data.  In particular, it would be
| convenient to have a "getOrNull" method on Option values when calling
| into legacy Java code, and to have an easy way to create a None if
| the raw value returned by legacy Java code is null, or a Some if
| not null.
These two functions exists in Scalaz

http://projects.workingmouse.com/public/scalaz/artifacts/latest/scaladoc/scalaz/Maybe.html#toNull
http://projects.workingmouse.com/public/scalaz/artifacts/latest/scaladoc/scalaz/Option$object.html#onull(A)

|
|
| I was also a bit surprised to discover that Some(null) is legal.  I
| thought the whole purpose of Option was not to have null values
| floating around.  Perhaps there should also be a Some.notNull(x)
| constructor that would throw an exception if x==null.
This discussion has been had. The purpose of Option is not to have null
floating around. It just solves that problem by consequence. Similarly,
the purpose of a car is not to generate heat from its engine bay. Option
is just an algebra like so many others.

|
| --
| Jim
|
|
|


- --
Tony Morris
http://tmorris.net/

Real-world problems are simply degenerate cases of pure mathematical
problems.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFIdEkUmnpgrYe6r60RAhqYAKDE5SukiFU/YDcDNpJkZ0BON4OxZgCgwYvp
oqPgjYQ7TtYbthDNQoTIThU=
=7ule
-----END PGP SIGNATURE-----


[scala] Re: Option vs null

by Jesper Nordenberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

How about this:

implicit def stringToFile(name : String) = new File(name)

/Jesper Nordenberg

Jim McBeath wrote:

> As a vehicle for helping me learn Scala, I have converted one of my
> Java programs over to Scala.  The Java code included a class with two
> methods overloading the same name, one with an optional File argument
> and the other with an optional String argument (representing a file
> name).  The Java methods looked something like this:
>
>     import java.io.File;
>     public class Test {
>         //f is optional, may be null
>         public void foo(String s, File f) { }
>
>         //name is optional may be null
>         public void foo(String s, String name) { }
>     }
>
> As part of the conversion to Scala, I wanted to use Option objects
> rather than using null to represent missing values.  After converting
> to Scala, the above code looked something like this:
>
>     import java.io.File
>     class Test {
>        
>         def foo(s:String, fOpt:Option[File]):Unit = { }
>
>         def foo(s:String, nameOpt:Option[String]):Unit = { }
>     }
>
> However, the compiler gives me the following error message:
>
>     test.scala:6: error: double definition:
>     method foo:(String,Option[String])Unit and
>     method foo:(String,Option[java.io.File])Unit at line 4
>     have same type after erasure: (java.lang.String,Option)Unit
>
> Is there an elegant solution for this?  I could of course change the
> names so as not to use overloading, or add an argument to one or the
> other method to disambiguate.  I thought about trying to coalesce the
> two methods into one, but I don't think I can declare an
> "Option[String or File]" type, and changing it to Option[Any] would
> weaken type-checking at caller sites.
>
> At the moment I have reverted the overloaded methods back to their
> original signature, accepting a nullable String or File rather than an
> Option, but I am hoping there is a better "Scala way" solution.
>
>
> There are a couple of small things that could be added to Scala
> to make it a little simpler to interface to legacy Java code that
> uses null as a marker for missing data.  In particular, it would be
> convenient to have a "getOrNull" method on Option values when calling
> into legacy Java code, and to have an easy way to create a None if
> the raw value returned by legacy Java code is null, or a Some if
> not null.  These two additions would make it a one-step operation
> to convert each way between an Option value and a maybe-null value.
> I have implemented these two changes in my code using the following
> little object:
>
>     object SomeOrNone {
>         class OptionOrNull[T](x:Option[T]) {
>             def getOrNull():T = if (x.isDefined) x.get else null.asInstanceOf[T]
>         }
>
>         implicit def optionOrNull[T](x:Option[T]) = new OptionOrNull(x)
>
>         def apply[T](x:T) = if (x==null) None else Some(x)
>     }
>
> I then use "import SomeOrNone" and "import SomeOrNone.optionOrNull"
> in the source files in which I want to be able to use the SomeOrNone
> creation method or the getOrNull method on an Option.  In order to
> simplify interfacing to legacy Java code, it would be nice to have the
> standard Option class include the getOrNull method, and to add an
> "orNone" constructor to the standard Some object so that I could say
> "Some.orNone(x)", which would return a None if x were null, else
> Some(x).
>
> I was also a bit surprised to discover that Some(null) is legal.  I
> thought the whole purpose of Option was not to have null values
> floating around.  Perhaps there should also be a Some.notNull(x)
> constructor that would throw an exception if x==null.
>
> --
> Jim
>


Re: [scala] Option vs null

by Viktor Klang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

or:
def foo(s:String, f:Either[File,String]):Unit = { }

And then you can match on it.

Cheers,
-V

On Wed, Jul 9, 2008 at 7:13 AM, Tony Morris <tmorris@...> wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


Jim McBeath wrote:
| As a vehicle for helping me learn Scala, I have converted one of my
| Java programs over to Scala.  The Java code included a class with two
| methods overloading the same name, one with an optional File argument
| and the other with an optional String argument (representing a file
| name).  The Java methods looked something like this:
|
|     import java.io.File;
|     public class Test {
|         //f is optional, may be null
|         public void foo(String s, File f) { }
|
|         //name is optional may be null
|         public void foo(String s, String name) { }
|     }
|
| As part of the conversion to Scala, I wanted to use Option objects
| rather than using null to represent missing values.  After converting
| to Scala, the above code looked something like this:
|
|     import java.io.File
|     class Test {
|         |         def foo(s:String, fOpt:Option[File]):Unit = { }
|
|         def foo(s:String, nameOpt:Option[String]):Unit = { }
|     }
|
| However, the compiler gives me the following error message:
|
|     test.scala:6: error: double definition:
|     method foo:(String,Option[String])Unit and
|     method foo:(String,Option[java.io.File])Unit at line 4
|     have same type after erasure: (java.lang.String,Option)Unit
|
| Is there an elegant solution for this?  I could of course change the
| names so as not to use overloading, or add an argument to one or the
| other method to disambiguate.  I thought about trying to coalesce the
| two methods into one, but I don't think I can declare an
| "Option[String or File]" type, and changing it to Option[Any] would
| weaken type-checking at caller sites.
Personally, I'd delete the String function and write a String -> File implicit (if that is not to your liking, I'd abstract it in away such that it does).


|
| At the moment I have reverted the overloaded methods back to their
| original signature, accepting a nullable String or File rather than an
| Option, but I am hoping there is a better "Scala way" solution.
|
|
| There are a couple of small things that could be added to Scala
| to make it a little simpler to interface to legacy Java code that
| uses null as a marker for missing data.  In particular, it would be
| convenient to have a "getOrNull" method on Option values when calling
| into legacy Java code, and to have an easy way to create a None if
| the raw value returned by legacy Java code is null, or a Some if
| not null.
These two functions exists in Scalaz

http://projects.workingmouse.com/public/scalaz/artifacts/latest/scaladoc/scalaz/Maybe.html#toNull
http://projects.workingmouse.com/public/scalaz/artifacts/latest/scaladoc/scalaz/Option$object.html#onull(A)


|
|
| I was also a bit surprised to discover that Some(null) is legal.  I
| thought the whole purpose of Option was not to have null values
| floating around.  Perhaps there should also be a Some.notNull(x)
| constructor that would throw an exception if x==null.
This discussion has been had. The purpose of Option is not to have null floating around. It just solves that problem by consequence. Similarly, the purpose of a car is not to generate heat from its engine bay. Option is just an algebra like so many others.

|
| --
| Jim
|
|
|


- --
Tony Morris
http://tmorris.net/

Real-world problems are simply degenerate cases of pure mathematical problems.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFIdEkUmnpgrYe6r60RAhqYAKDE5SukiFU/YDcDNpJkZ0BON4OxZgCgwYvp
oqPgjYQ7TtYbthDNQoTIThU=
=7ule
-----END PGP SIGNATURE-----




--
Viktor Klang
Rogue Software Architect

Re: [scala] Option vs null

by Barry Kelly-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Tony Morris <tmorris@...> wrote:

> Personally, I'd delete the String function and write a String -> File
> implicit

I sincerely hope you aren't serious. Strings aren't files, and
implicitly converting one to the other is a gross sanity violation -
consider a lexical analyzer that can scan string text or source from a
file (and thus might be overloaded on both): in this case, the string
isn't a logical pointer to the file, but rather the other way around,
the file is a pointer to the source text.

Would you then suggest a File -> String implicit? So that there is an
asymmetrical bidirectional conversion between strings and files?

> (if that is not to your liking, I'd abstract it in away such
> that it does).

I don't understand that sentence.

(I also wish someone would fix the missing Reply-To header in this
mailing list...)

-- Barry

--
http://barrkel.blogspot.com/

Re: [scala] Option vs null

by tmorris :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Barry Kelly wrote:

> Tony Morris <tmorris@...> wrote:
>
>> Personally, I'd delete the String function and write a String ->
>> File implicit
>
> I sincerely hope you aren't serious. Strings aren't files, and
> implicitly converting one to the other is a gross sanity violation
> - consider a lexical analyzer that can scan string text or source
> from a file (and thus might be overloaded on both): in this case,
> the string isn't a logical pointer to the file, but rather the
> other way around, the file is a pointer to the source text.
>
> Would you then suggest a File -> String implicit? So that there is
> an asymmetrical bidirectional conversion between strings and files?
>
I'm serious (and so is Jesper it seems). The sentence "Strings aren't
Files" doesn't parse for me because I reason about software using a
different method and without labels. The structure of a File
(java.io.File) as an algebra is isomorphic to a String (which happens
to contradict the statement "Strings aren't Files" - yes they most
definitely are!). Given this isomorphism, I have no problem writing an
implicit inverse.

>
>> (if that is not to your liking, I'd abstract it in away such that
>> it does).
>
> I don't understand that sentence.
It seems that the OP merely wants function composition with the
aforementioned implicit function, however, Scala makes function
composition quite laborious (although, as I mentioned on another
thread, I have shortened this somewhat). Otherwise, whatever functions
are acting over String/File could be abstracted. To answer this more
specifically, I'd need to know these functions.

>
> (I also wish someone would fix the missing Reply-To header in this
> mailing list...)
>

It's been discussed numerous times and I think the conclusion was to
leave it as is. I don't know the details because I seem to care less
than others do, but you might be interested in looking at these
previous threads to get more details.

> -- Barry
>


- --
Tony Morris
http://tmorris.net/

Real-world problems are simply degenerate cases of pure mathematical
problems.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFIdSmrmnpgrYe6r60RAhvrAJ91rYmSHBu9jTI0JECvt8XDL0ZGUgCgjKNb
R4ETLgUBdviPkdVGSQR39Nc=
=Y874
-----END PGP SIGNATURE-----


Re: [scala] Option vs null

by Jamie Webb-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 2008-07-09 19:35:36 Barry Kelly wrote:
> > I sincerely hope you aren't serious. Strings aren't files, and
> > implicitly converting one to the other is a gross sanity violation
> > - consider a lexical analyzer that can scan string text or source
> > from a file (and thus might be overloaded on both):

No, it shouldn't be. You have two methods that do different things, so
they should have different names. (I agree that Tony's implicits are a
really dumb idea, just not for this reason.)

On 2008-07-10 07:12:12 Tony Morris wrote:
> I'm serious (and so is Jesper it seems). The sentence "Strings aren't
> Files" doesn't parse for me because I reason about software using a
> different method and without labels. The structure of a File
> (java.io.File) as an algebra is isomorphic to a String (which happens
> to contradict the statement "Strings aren't Files" - yes they most
> definitely are!). Given this isomorphism, I have no problem writing an
> implicit inverse.

This is utter nonsense. If you don't like your sequences of bits being
labelled to indicate their purpose, perhaps you should go back and
program in BCPL.

/J

Re: [scala] Option vs null

by Barry Kelly-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Tony Morris wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Barry Kelly wrote:
> > Tony Morris <tmorris@...> wrote:
> >
> >> Personally, I'd delete the String function and write a String ->
> >> File implicit
> >
> > I sincerely hope you aren't serious. Strings aren't files, and
> > implicitly converting one to the other is a gross sanity violation
> > - consider a lexical analyzer that can scan string text or source
> > from a file (and thus might be overloaded on both): in this case,
> > the string isn't a logical pointer to the file, but rather the
> > other way around, the file is a pointer to the source text.
> >
> > Would you then suggest a File -> String implicit? So that there is
> > an asymmetrical bidirectional conversion between strings and files?
> >
> I'm serious (and so is Jesper it seems). The sentence "Strings aren't
> Files" doesn't parse for me

I think we are speaking in different languages. Here's an explanation of
what I mean when I use words like "Strings", "Files", and "is" (plural:
"are") (I trust you know what "not" means :) :-

"A String" is an instance (i.e. a value) of the java.lang.String class,
where the java.lang.String class is intended to represent immutable
arrays of characters - i.e. character strings, aka text information.

"A File" is an instance of the java.io.File class, where the
java.io.File class is intended to represent a file or directory path
name.

When I use the word "is", I am asserting some level of semantic
equivalency between the subject on the left of the "is" and the object
on the right, for some context, which itself may be explicit or implied
by prior sentences or emails. As in any human language, there is a
little fuzziness in here. I hope you are able to follow ;)

E.g.: when I say "this String is the path to a file", I am asserting
that the *meaning* (in the programmer's mind) of 'this' String value is
that it can be interpreted by the OS as the location of a file in some
filesystem.

So when I say "Strings aren't Files", I am asserting that there isn't a
semantic equivalency between Strings and Files. The basis of my claim is
that their types have different semantic intent, as documented in the
Java platform documentation[1]. Certainly, some Strings may be paths to
files, and many Files are paths to files (and not directories, or
non-existent files or directories), but I trust a trivial survey of
real-life programs will demonstrate that the vast majority of Strings
are not employed as paths to files.

[1] See:
http://java.sun.com/javase/6/docs/api/java/lang/String.html
http://java.sun.com/javase/6/docs/api/java/io/File.html

I am of course interested in pragmatic concerns over theoretical
correspondences; many different things can be mapped to a single set,
and each operation shown to be mappable to a corresponding equivalent
operation on the single set, and thus be shown to be isomorphic, but
this isn't interesting for solving real-world problems. In order for our
solutions to help with the real world, the elements of our problem
domain need to map onto real objects in the real world, where
theoretical correspondences between our abstractions no longer apply.

To make that more concrete, let me give an example:

- I might use a location for String values called 'name', and intend for
that to map to a person in the real world (assuming other constraining
factors that remove ambiguity).

- I might similarly use a location for File values called
'homeDirectory', and intend for it to map to some range of iron oxide
particles contained in a metal box underneath my desk.

Now, String and File might have, with appropriate contortions, an
isomorphic set of values and operations, but there is in no way a
similar isomorphism between a person in the real world and a pile of
rust inside a small metal box - at any level humans (who pay software
developers their wages) care about.

These distinctions (the kinds between Strings and Files) are important
in software engineering, because humans are fallible. If everybody used
Strings both when they needed names of people and paths for files on
disk, there is a danger (because they are fallible, don't forget that)
that they might confuse the two somewhere, and mistakenly look for a
person inside a metal box, or insult someone by describing them as a bit
rusty.

This is why I say things like "Strings aren't Files". Because if we go
down that path, we have lost a valuable guard against human fallibility.
By enabling implicit conversions between Strings and Files, we muddy the
gap between the two.

And most importantly, because Strings and Files are rarely put to
semantically equivalent uses, implicit conversions between the two are
ambiguous and conflicting. I tried to make this clear to you by giving
you an example; if you create a String -> File implicit conversion, and
justify it by appealing to isomorphism, then you can't object to a File
-> String conversion that was the inverse. Unfortunately, an alternative
obvious File -> String conversion also exists; that of reading the
contents of a file on disk into memory as a String; and we have the
aforementioned ambiguity and conflict.

> because I reason about software using a
> different method and without labels.

Labels are useful. Function and parameter names are labels. I wonder how
successfully you program in the large without named functions or
parameters? Even the lambda calculus needs a parameter name! :)

> The structure of a File
> (java.io.File) as an algebra is isomorphic to a String

I have explained why an isomorphism between any two pairs of (set and
operations on elements of the set) is not particularly interesting for
solutions that people pay wages for - i.e. representing real-world
problems - and also why it is important that the distinction between
what may theoretically be isomorphic algebras is made clear.

In summary, your justification for your suggestion strikes me as naive,
narrow-minded and dangerous. It seems to ignore the real world, and the
very real complexities of software engineering as practiced
professionally.

> > (I also wish someone would fix the missing Reply-To header in this
> > mailing list...)
>
> It's been discussed numerous times and I think the conclusion was to
> leave it as is. I don't know the details because I seem to care less
> than others do, but you might be interested in looking at these
> previous threads to get more details.

It's unfortunate for me primarily because it breaks threading in my mail
reader; and the default action for a reply drops the mailing list from
the conversation.

The conversation moves from the mailing list folder to my inbox because
the sender of the reply is no longer the mailing list, and the mailing
list doesn't deliver duplicates when it is CC'd on a reply.

As it stands, I don't think I'll be contributing many replies to the
Scala mailing list, as I don't want to clog the aforementioned inbox.

-- Barry

--
http://barrkel.blogspot.com/

Re: [scala] Option vs null

by tmorris :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Barry Kelly wrote:
| Tony Morris wrote:
|
|> -----BEGIN PGP SIGNED MESSAGE-----
|> Hash: SHA1
|>
|> Barry Kelly wrote:
|>> Tony Morris <tmorris@...> wrote:
|>>
|>>> Personally, I'd delete the String function and write a String ->
|>>> File implicit
|>> I sincerely hope you aren't serious. Strings aren't files, and
|>> implicitly converting one to the other is a gross sanity violation
|>> - consider a lexical analyzer that can scan string text or source
|>> from a file (and thus might be overloaded on both): in this case,
|>> the string isn't a logical pointer to the file, but rather the
|>> other way around, the file is a pointer to the source text.
|>>
|>> Would you then suggest a File -> String implicit? So that there is
|>> an asymmetrical bidirectional conversion between strings and files?
|>>
|> I'm serious (and so is Jesper it seems). The sentence "Strings aren't
|> Files" doesn't parse for me
|
| I think we are speaking in different languages. Here's an explanation of
| what I mean when I use words like "Strings", "Files", and "is" (plural:
| "are") (I trust you know what "not" means :) :-
|
| "A String" is an instance (i.e. a value) of the java.lang.String class,
| where the java.lang.String class is intended to represent immutable
| arrays of characters - i.e. character strings, aka text information.
|
| "A File" is an instance of the java.io.File class, where the
| java.io.File class is intended to represent a file or directory path
| name.
|
| When I use the word "is", I am asserting some level of semantic
| equivalency between the subject on the left of the "is" and the object
| on the right, for some context, which itself may be explicit or implied
| by prior sentences or emails. As in any human language, there is a
| little fuzziness in here. I hope you are able to follow ;)
|
| E.g.: when I say "this String is the path to a file", I am asserting
| that the *meaning* (in the programmer's mind) of 'this' String value is
| that it can be interpreted by the OS as the location of a file in some
| filesystem.
|
| So when I say "Strings aren't Files", I am asserting that there isn't a
| semantic equivalency between Strings and Files. The basis of my claim is
| that their types have different semantic intent, as documented in the
| Java platform documentation[1]. Certainly, some Strings may be paths to
| files, and many Files are paths to files (and not directories, or
| non-existent files or directories), but I trust a trivial survey of
| real-life programs will demonstrate that the vast majority of Strings
| are not employed as paths to files.
|
| [1] See:
| http://java.sun.com/javase/6/docs/api/java/lang/String.html
| http://java.sun.com/javase/6/docs/api/java/io/File.html

However, when you analyse the details, you discover an isomorphism of
the structure of each algebra. It is bit like saying "construction of
logic theorems and computer programming are not the same thing", since
they "seem" and "feel" like different things. Indeed, they have
different "fuzzy" connotations attached to each. However, fundamentally
we *know* they are empirically the same thing (C-H Isomorphism) and that
any suggestion that they are different is merely the projection of our
own narrow (and prior to the discovery by Curry-Howard, ignorant) views.

|
| I am of course interested in pragmatic concerns over theoretical
| correspondences; many different things can be mapped to a single set,
| and each operation shown to be mappable to a corresponding equivalent
| operation on the single set, and thus be shown to be isomorphic, but
| this isn't interesting for solving real-world problems. In order for our
| solutions to help with the real world, the elements of our problem
| domain need to map onto real objects in the real world, where
| theoretical correspondences between our abstractions no longer apply.
|
| To make that more concrete, let me give an example:
|
| - I might use a location for String values called 'name', and intend for
| that to map to a person in the real world (assuming other constraining
| factors that remove ambiguity).
|
| - I might similarly use a location for File values called
| 'homeDirectory', and intend for it to map to some range of iron oxide
| particles contained in a metal box underneath my desk.
When you say "intend it to map to ..." I say "define functions across
the structure". This is just more accurate reasoning to remove the
fuzziness. Once the fuzziness is gone, I'm sure you'll shift your
position. That you, personally, to appease yourself and your biases,
independently of the software, which exists externally to you, wish to
project a different fuzzy meaning on two equivalent structures, is only
going to contribute to - at worst - an impoverished view for you of what
is really going on.

|
| Now, String and File might have, with appropriate contortions, an
| isomorphic set of values and operations, but there is in no way a
| similar isomorphism between a person in the real world and a pile of
| rust inside a small metal box - at any level humans (who pay software
| developers their wages) care about.
WTF?

|
| These distinctions (the kinds between Strings and Files) are important
| in software engineering, because humans are fallible. If everybody used
| Strings both when they needed names of people and paths for files on
| disk, there is a danger (because they are fallible, don't forget that)
| that they might confuse the two somewhere, and mistakenly look for a
| person inside a metal box, or insult someone by describing them as a bit
| rusty.

These fallacious distinctions are *incredibly detrimental* to software
development because humans are fallible - even with just my own personal
anecdotes over the years. I have met your assertion with my own, which I
am committed to as much as you are yours. The question now is, are you
prepared to explore this path and possibly shift position? I am, but
you'll have to bring some new arguments to the table.

|
| This is why I say things like "Strings aren't Files". Because if we go
| down that path, we have lost a valuable guard against human fallibility.
| By enabling implicit conversions between Strings and Files, we muddy the
| gap between the two.
We have improved our reasoning process by identifying the true structure
of our program, instead of artificially and arbitrarily elevating the
status of labels that we wish to attach to it.

Would you object to me calling this "Option"? How about "Maybe"?

sealed trait Null[+A]
final case object Nup extends Null[Nothing]
final case class Yep[+A](a: A) extends Null[A]

What about this? What do you call it?

sealed trait Disjunction[+A, +B]
final case class OneTheorem(a: A) extends Disjunction[A, Nothing]
final case class TheOtherTheorem(b: B) extends Disjunction[Nothing, B]

The Scala community agreed that we'd call it "Either", but does it matter?

Here are some facts; we can define a covariant functor and a monad
across the Null structure. For some other structures, this is not true.
Indeed, not for Disjunction! (it is not even well-kinded; we fail
immediately). These are just observations about the so-called *real
world*. If I were to vanish tomorrow, these observations stand.

|
| And most importantly, because Strings and Files are rarely put to
| semantically equivalent uses, implicit conversions between the two are
| ambiguous and conflicting. I tried to make this clear to you by giving
| you an example; if you create a String -> File implicit conversion, and
| justify it by appealing to isomorphism, then you can't object to a File
| -> String conversion that was the inverse. Unfortunately, an alternative
| obvious File -> String conversion also exists; that of reading the
| contents of a file on disk into memory as a String; and we have the
| aforementioned ambiguity and conflict.
This fuzzy notion of "semantically equivalent uses" is ill-defined and
is unlikely to ever eventuate into a consistent definition. I'm sure
you'll try and I'll probably have to respond with a Socratic
midwife-like response, until eventually the mailing list gets annoyed
with me :)

Nevertheless, if I find myself "being fuzzy" or "unable to define
consistently under critical examination", either through self-reflection
or assistance from peers, then I have a mental defense system that sets
off warning bells, which is why I never use such informal reasoning. It
misleads us only into states of mental inconsistency.

|
|> because I reason about software using a
|> different method and without labels.
|
| Labels are useful. Function and parameter names are labels. I wonder how
| successfully you program in the large without named functions or
| parameters? Even the lambda calculus needs a parameter name! :)
Labels are useful, but they denote a structure or concept. The same
label for the same structure does not make the structures different,
which is at the very essence of the computer program (again, C-H
Isomorphism).

What label do you attach to this structure?

\a b -> b
\a b -> a b
\a b -> a (a b)
\a b -> a (a (a b))

Most people call it "the set of natural numbers". We can run with that.
In fact, you can call it "poop" if you like. As long as we have
agreement on the structure itself, it is not going to matter to the
intangible software.

|
|> The structure of a File
|> (java.io.File) as an algebra is isomorphic to a String
|
| I have explained why an isomorphism between any two pairs of (set and
| operations on elements of the set) is not particularly interesting for
| solutions that people pay wages for - i.e. representing real-world
| problems - and also why it is important that the distinction between
| what may theoretically be isomorphic algebras is made clear.
|
| In summary, your justification for your suggestion strikes me as naive,
| narrow-minded and dangerous. It seems to ignore the real world, and the
| very real complexities of software engineering as practiced
| professionally.
The "real world" where "real complexities" are "practiced professionally"?

Oh I know, you mean the one where there are mathematical structures that
exist independently of our own biases, yet we feel compelled to project
labels on them and pretend that other labels denoting the exact same
structure are in some way distinct because we take comfort in our own
ignorance? Or, are you talking about a different real world to the one I
find myself in? I find the above paragraph quite telling and my sarcasm
is not intended to belittle, but display my shock.

You're stepping into the land of being blatant with logical fallacy here.

To address your statement more bluntly (let's assume good will and not
fallaciousness as always), in this real world, software is *seldom
practiced professionally*. How many programmers do you know who have
none or very little idea about the very basic and essential fundamental
tenets of the theory of computation? Since we're on this topic, turn to
the person next to you and say "Curry-Howard Isomorphism" (or insert
equivalent should you so choose). What response did you attract? I get
googley eyes and a "WTF are you talking about?' look. This would be OK,
if the respondent had independently discovered this themselves and just
not had a label (C-H-I) to attach to it, but I am assuming this is not
the case.

Now go to your local mechanic and say "spark plug"; same response?
Didn't think so.

Furthermore, the so-called "real complexities of software engineering"
have very little to do with how we label structures. I am fully aware of
the deception in industry that dilutes the true contentions in computer
programming (like you know, the halting problem for example). In any
case, the evidence is all around you. I mean "Java bean"? "Actor"?
"LINQ"? Do these words have any meaning at all? For example, a smart
programmer looks at LINQ and just says "oh that's a glorified monad".
Does this act of "renaming" cause him problems? Actually, quite the
opposite - since he can show that they are precisely the same thing (in
fact, a specialisation in this case), he can draw on his understanding
of *the concept of monads* and fully understand LINQ in the flash of a
brief thought.

Software is in the abstract, always was and is today - they just don't
tell you that at school anymore (I do in my tutorials, but always
afterward in spare time where students are keen to learn). Ever wonder
why Microsoft hit it so big? Can you really make money with an
intangible artifact? The naysayers didn't think so, but at least all
parties (Microsoft and the naysayers) were equipped with the knowledge
that software is intangible. That we find ourselves in a somewhat
altered (distorted?) situation today does not alter this fact.

A brief and related thought fondly reminds of the gross ineptitude that
surrounded me in my recent, but foregone days working for IBM Software
Group :) I won't share it with you, for brevity's sake :)

|
|>> (I also wish someone would fix the missing Reply-To header in this
|>> mailing list...)
|> It's been discussed numerous times and I think the conclusion was to
|> leave it as is. I don't know the details because I seem to care less
|> than others do, but you might be interested in looking at these
|> previous threads to get more details.
|
| It's unfortunate for me primarily because it breaks threading in my mail
| reader; and the default action for a reply drops the mailing list from
| the conversation.
|
| The conversation moves from the mailing list folder to my inbox because
| the sender of the reply is no longer the mailing list, and the mailing
| list doesn't deliver duplicates when it is CC'd on a reply.
|
| As it stands, I don't think I'll be contributing many replies to the
| Scala mailing list, as I don't want to clog the aforementioned inbox.
|
| -- Barry
|
I'm out of breath anyway, how about you? :)

- --
Tony Morris
http://tmorris.net/

Real-world problems are simply degenerate cases of pure mathematical
problems.


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFIdUvYmnpgrYe6r60RArorAJ0TMXORb5HlaDX2sxpROrL4aRjFFwCfW62u
wPU8MlEXSf6UiMgV9v/4lS0=
=jYRU
-----END PGP SIGNATURE-----


Re: [scala] Option vs null

by Jim McBeath-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Jul 08, 2008 at 10:02:06PM -0700, Jim McBeath wrote:
> As a vehicle for helping me learn Scala, I have converted one of my
> Java programs over to Scala.  The Java code included a class with two
> methods overloading the same name, one with an optional File argument
> and the other with an optional String argument (representing a file
> name).

Thanks for the suggestions.

Tony Morris wrote:
> Personally, I'd delete the String function and write a String -> File
> implicit (if that is not to your liking, I'd abstract it in away such that
> it does).

The string I pass in may be a name without a path component,
to be turned into a File using a base directory in the object,
so I don't think I can define this implicit conversion.

> These two functions exists in Scalaz
> http://projects.workingmouse.com/public/scalaz/artifacts/latest/scaladoc/scalaz/Maybe.html#toNull
> http://projects.workingmouse.com/public/scalaz/artifacts/latest/scaladoc/scalaz/Option$object.html#onull(A)

I'm happy to hear that there is a standard solution, but for now I
think I will stick to my little object rather than add a dependency
to sbaz.  It would be nice if the above-referenced doc pages had
a one-line description of what each method does.  Unfortunately,
I am not familiar enough with the terminology used in those classes
to understand what all of the methods do based solely on their
names and signatures.  I will look at the source code if I reach
the point of really wanting to know.

> This discussion has been had. The purpose of Option is not to have null
> floating around. It just solves that problem by consequence. Similarly,
> the purpose of a car is not to generate heat from its engine bay. Option
> is just an algebra like so many others.

Thanks for pointing this out, I will see if I can find these
discussions in the archives.

Viktor Klang wrote:
> def foo(s:String, f:Either[File,String]):Unit = { }
> And then you can match on it.

An interesting suggestion, but not quite usable for my situation.
I want to be able to take an Option value returned by another method
that is interfacing to a legacy Java method, and pass that directly
back to my method.

The combination of the suggestions about using implicit conversions
and Either got me thinking about how I might be able to use those
two together to do what I want.  I have started playing around with
various implicit conversions and combinations of Option and Either.
I don't yet have a satisfactory solution, but in any case it is
helping me with my other goal of learning the language and concepts.
The learning is more important to me than the solution for this
particular problem.

And I am enjoying the continuing discussion about Strings and
Files. :-)

--
Jim

Re: [scala] Option vs null

by Burak Emir-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Jim,

my advice:
1. just stay away from implicits
2. do not use overloading

instead of Option[Either[File,String]], you could define a special type for your input needs

abstract class MyInput
case class WithString(s:String) extends MyInput
case class WithFile(f:File) extends MyInput
case object WithNothing extends MyInput

def foo(f: String, bar:MyInput) = bar mach {
  case ...
}


foo("bla", WithNothing)

hope this helps,
Burak

On Thu, Jul 10, 2008 at 2:24 AM, Jim McBeath <scala@...> wrote:
On Tue, Jul 08, 2008 at 10:02:06PM -0700, Jim McBeath wrote:
> As a vehicle for helping me learn Scala, I have converted one of my
> Java programs over to Scala.  The Java code included a class with two
> methods overloading the same name, one with an optional File argument
> and the other with an optional String argument (representing a file
> name).

Thanks for the suggestions.

Tony Morris wrote:
> Personally, I'd delete the String function and write a String -> File
> implicit (if that is not to your liking, I'd abstract it in away such that
> it does).

The string I pass in may be a name without a path component,
to be turned into a File using a base directory in the object,
so I don't think I can define this implicit conversion.
I'm happy to hear that there is a standard solution, but for now I
think I will stick to my little object rather than add a dependency
to sbaz.  It would be nice if the above-referenced doc pages had
a one-line description of what each method does.  Unfortunately,
I am not familiar enough with the terminology used in those classes
to understand what all of the methods do based solely on their
names and signatures.  I will look at the source code if I reach
the point of really wanting to know.

> This discussion has been had. The purpose of Option is not to have null
> floating around. It just solves that problem by consequence. Similarly,
> the purpose of a car is not to generate heat from its engine bay. Option
> is just an algebra like so many others.

Thanks for pointing this out, I will see if I can find these
discussions in the archives.

Viktor Klang wrote:
> def foo(s:String, f:Either[File,String]):Unit = { }
> And then you can match on it.

An interesting suggestion, but not quite usable for my situation.
I want to be able to take an Option value returned by another method
that is interfacing to a legacy Java method, and pass that directly
back to my method.

The combination of the suggestions about using implicit conversions
and Either got me thinking about how I might be able to use those
two together to do what I want.  I have started playing around with
various implicit conversions and combinations of Option and Either.
I don't yet have a satisfactory solution, but in any case it is
helping me with my other goal of learning the language and concepts.
The learning is more important to me than the solution for this
particular problem.

And I am enjoying the continuing discussion about Strings and
Files. :-)

--
Jim



--
Burak Emir
--
http://burak.emir.googlepages.com

[scala] Re: Option vs null

by Jesper Nordenberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Barry Kelly wrote:
> So when I say "Strings aren't Files", I am asserting that there isn't a
> semantic equivalency between Strings and Files. The basis of my claim is
> that their types have different semantic intent, as documented in the
> Java platform documentation[1]. Certainly, some Strings may be paths to
> files, and many Files are paths to files (and not directories, or
> non-existent files or directories), but I trust a trivial survey of
> real-life programs will demonstrate that the vast majority of Strings
> are not employed as paths to files.

I agree, but this semantic difference is not enforced in any way by the
File class, any string can be mapped to a File object. If you use an
invalid file path the compiler/runtime will not complain until you try
to access the file. My point is, what additional safety have you
achieved by writing "someFileOperation(new File(name))" compared to
"someFileOperation(name)"? None.

IMO, the methods in the file class could as well be static methods that
take the file name as a string parameter. The File class only purpose is
to provide a method context which contains the file name.

/Jesper Nordenberg


Re: [scala] Re: Option vs null

by tmorris :: Rate this Message: