Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Amen. How about some language keywords like "readable" and "writeable"?

public class Foo { public readable int canSeeeMeButCantChange; public writeable int cantReadMe; public int existingBehavior; }

These are pretty simple changes to the compiler and verifier. You would make canSeeeMeButCantChange an invalid "left hand" variable in the compiler, and the verifier would have to check for any writes to the fields. cantReadMe would be an invalid right hand variable, and a similar check for the verifier. Any other public field behaves as normal.



The other "Missing feature" is null safe ".". Other languages have it, but I don't know what the technical name is... basically:

Integer val = some.other.chain.of.objects.value;

In Java, this code has a huge potential for NullPointerExceptions. Instead a new operator (yes, I know) like:

Integer val = some.?other.?chain.?of.?objects.?value;

If any of the intermediate objects are null, the whole assignment becomes null. This could be done with a smarter compiler (easy way), or a new JVM bytecode (probably 'better' but not easy).


This is solved in a more general way in Java 8 via monadic optionals. The basic idea is to wrap your nullable objects in an Optional<T>, which then both forces you to deal with the possibility of the value being absent and gives you good tools for doing so. Your example, with Optional, looks like this:

T obj = ...;

Optional.of(obj).map(T::some).map(U::other).map(V::methods).getOrElse(null);

Not quite as clean syntactically, but much more general, as the same operations can be applied to other monadic objects.


The sugar your parent proposed would still be nice and has precedent in other languages with option types. Swift has something very similar[0], and Rust is debating it[1]. Haskell's do-notation and Scala's for-comprehension are other solutions to the same general problem of conveniently using option types.

It may be a good thing to only support that sort of convenience for option types and not for nulls, in order to further encourage their use. Although using nullable types is already pretty darn convenient!

[0]: https://developer.apple.com/library/prerelease/ios/documenta... [1]: https://github.com/rust-lang/rfcs/pull/204


This is kind of a pedantic distinction, but the behavior you've described is actually Functor behavior; I think Monads allow for Functor-like behavior as part of their definition (not sure, I'm neither a category theorist nor an experienced Haskeller), but their use is something a little bit different. Monads allow you to do two things:

1) Lift regular values into monadic ones in a generic way. Let's say that we have two Monads - Optional and List. There should be a way such that we can take a non-monadic value (the part that will go inside) and turn it into a Monad. So, assuming Monad is a Java-like abstract class, the following should be possible:

    Monad<String> m1 = Optional.lift("hello");
    Monad<String> m2 = List.lift("hello");
2) Flat-map, typically called bind in this context. Given a monad and a function that takes a value and returns a monad, we should have some way of combining the resulting monads if we were to map this function over the first monad's internal value. So for instance, given an optional string, and a function that takes a string and returns an optional int, we should have some way of combining the Optional<Optional<Integer>> into just an Optional<Integer>. So, in the following contrived example...

  // Returns a UTF8 string value from a database, may fail
  public Optional<String> getUtf8Name() { ... }

  // Returns the length of a String if it contains exclusively ascii characters
  public Optional<Integer> getAsciiLength(String str) { ... }
... you can compare the differences between it and the Functor's map:

  Optional<Integer> asciiLength = getUtf8Name().bind(getAsciiLength);
  Optional<Integer> otherAsciiLength = getUtf8Name().map(getAsciiLength).getOrElse(Optional.absent());
As it turns out, you can implement the Functor's map method in a generic way using lift and bind.

  public abstract class Monad<A> implements Functor<A> {

    /**
     * Implements Functor's map method.
     */
    @Override
    public <B> Monad<B> map(Function<A, B> fn) {
      return this.bind( innerValue -> this.lift(fn.apply(innerValue)) );
    }

  }


    Monad<String> m1 = Optional.lift("hello");
    Monad<String> m2 = List.lift("hello");

Shouldn't that be

    Option<String> m1 = Optional.lift("hello");
    List<String> m2 = List.lift("hello"); 
?


This is called null-value propagation. It's coming to C# (6) this year.


Groovy does this, although frustratingly not with array accesses last I checked.


I requested array accesses on the Groovy mailing list 7 years ago, see http://groovy.329449.n5.nabble.com/Indexed-properties-td3396...

I never did fill out a GEP but you could try your luck by subbing one, see http://docs.codehaus.org/display/GroovyJSR/Groovy+Enhancemen...


Is that not what final does?

I'd be interested in seeing C#-like getters and setters. As long as they're just getting and setting, they're implied, but if you want to introduce a check or some other logic, you can do so without changing the signature of the class.

Groovy does some of this, but it requires you to use the name of the field - ie. person.age will check for a getAge() method first, then fall back on the "age" field. I quite like that methods have verb-names, but I don't want to verb my fields.


Yes, sort of like final... but different.

I was thinking this is more for _public_ variables... so like internally, a class could modify it's own readable fields, but code external could read only.


I do like how C# handled this, FWIW.

  public int MyProperty{
    get; //public
    private set; //private-only setter
  }
but obviously there are a lot of ways to skin that cat.


Methods that actually do something should be verbs, but if it's just reading a property it should look like it's just reading a property. And having all the methods on a class start with get* is a pain for autocompletion.


Hmm. I guess you're right. I dislike Groovy in other areas so it's not a path I've gone deep down.

Especially for private APIs i Java I have actually tended to default to public final members, without verbs.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: