andrewducker: (Default)
[personal profile] andrewducker
I want to be able to retrieve a value and then branch on its value, all in
one step. For some reason it irks me to have to say:
var blah = GetBlah();
if(blah != null)
{
//Do Stuff With blah
}

I want to say

if((var blah = GetBlah) != null)
{
//Do stuff with blah
}

I'm not sure why the extra line bothers me - possibly because it's a
pattern I keep having to repeat in my code, and any pattern I repeat irks
me after a while. That's why computers are there, to stop you having to do
the same thing over and over again.
Page 1 of 3 << [1] [2] [3] >>

Date: 2011-06-20 12:44 pm (UTC)
simont: A picture of me in 2016 (Default)
From: [personal profile] simont
If nothing else, the latter might have the useful effect of limiting the scope of 'blah', ensuring you didn't use it in an accidental or unclear way further down the function...

Date: 2011-06-20 12:52 pm (UTC)
From: [identity profile] call-waiting.livejournal.com
Can you at least do the C'ish

var blah;
if ((var = getBlah()) != null)
{
  //Do stuff with blah
}


?

Date: 2011-06-20 12:53 pm (UTC)
From: [identity profile] strawberryfrog.livejournal.com
Hm, some sort of macro, hashdefine or metaprogramming sytem is what's needed to do this right.

The closest you could get in C# would be an extension method using some generics and lambdas:


public static T DoIfNotNull<T>(this T value, Action<T> action) where T: class
{
if (value != null)
{
action(value);
}

// return the value for further chaining
return value;
}


Then you could code:

GetBlah().DoIfNotNull(blah => DoStuffWith(blah));

of course there are variations on this like

public static U DoIfNotNull<T, U>(this T value, Func<T, U> func) where T : class
{
U result = default(U);

if (value != null)
{
result = func(value);
}

return result;
}


.. so then your action can change the type and you can still chain methods.
Edited Date: 2011-06-20 12:56 pm (UTC)

Date: 2011-06-20 01:13 pm (UTC)
From: [identity profile] strawberryfrog.livejournal.com
In general yes, since (blah = getBlah()) returns the value assigned to blah.
You'd have to declare blah without using "var" though, unless there's an assignment on the same line the type inference has nothing to work on.

so this works

string blah;
if ((blah = getBlah()) != null)
{
//Do stuff with blah
}

private string getBlah()
{ ... }

Date: 2011-06-20 01:17 pm (UTC)
From: [identity profile] strawberryfrog.livejournal.com
If it's more than a few lines, you can put it in it's own method. I don't like long lambdas. A long lambda for me is > 2 statements.


// code is actually shorter - method is auto cast to action
getBlah().DoIfNotNull(SomeMethod);

...

private void SomeMethod(string blah)
{
...
}


Date: 2011-06-20 01:17 pm (UTC)
From: [identity profile] steer.livejournal.com
Related but not quite what you're after is Java 7's "null-safe" handling:

http://metoojava.wordpress.com/2010/11/15/java-7-awesome-features/

It's an interesting language feature I've not seen elsewhere that I hope spreads.

Date: 2011-06-20 01:34 pm (UTC)
From: [identity profile] call-waiting.livejournal.com
You'd have to declare blah without using "var" though

Ah yes, I'd forgotten that C# has type inference; I'd assumed that Andy's 'var' was pseudocode, heh.

Date: 2011-06-20 01:43 pm (UTC)
From: [identity profile] strawberryfrog.livejournal.com
it's very limited type inference. C# just looks for var foo = SomeExpression; and replaces "var" with the type of SomeExpression

The stuff that OCaml (and F#) do with type inference is just amazing.

Date: 2011-06-20 02:11 pm (UTC)
From: [identity profile] strawberryfrog.livejournal.com
It does type inference across the whole method, so in let f a b = a + b + 100, the type a, b and the return type of f are all infered as int.

It does the equivalent of generics automatically, so let makeTuple a b = (a, b) is the same as in C# Tuple<A, B> MakeTupple<A, B>(A a, B b) { ... }
Edited Date: 2011-06-20 02:13 pm (UTC)

Date: 2011-06-20 05:12 pm (UTC)
From: [identity profile] skington.livejournal.com
Perl lets you do that, but not quite as much as you'd want.

You can say

if (my $blah = get_blah()) {
...
}

but not

if (my $blah = get_blah() and $blah->can('do_stuff')) {
$blah->do_stuff();
}

because $blah doesn't exist when the second part of the conditional is run. You need to say

if (my $blah = get_blah()) {
if ($blah->can('do_stuff')) {
$blah->do_stuff();
}
}

instead.

Date: 2011-06-20 06:33 pm (UTC)
From: [identity profile] call-waiting.livejournal.com
Also, Haskell. <3

Date: 2011-06-20 06:49 pm (UTC)
From: [identity profile] call-waiting.livejournal.com
I have a vague recollection that some language I used to know had a similar feature. It might be Verisity 'E', but I don't remember it having exactly this. It did have some very neat functional list operators anyway, and I think it might have been possible to easily construct an idiom that did that, but i can't remember enough of the details to work out if it's possible.

It also strongly reminds me of Icon's goal-directed evaluation, but since Icon doesn't have any OO features and very very limited structures, I'm pretty sure it doesn't have anything quite like this; but if it *did*, it would support this sort of thing straight out of the box.

(I recommend giving Icon a once-over for curiosity's sake, by the way; it's an interesting little language, primarily because of the goal-oriented evaluation and generation. )

Date: 2011-06-20 07:18 pm (UTC)
From: [identity profile] cartesiandaemon.livejournal.com
Hm. I was thinking that C and C++ can do that, but didn't follow the thought through to the conclusion. I can't remmeber if C or C++ allow variable declaration in any statements other than for loops?

However, I don't think I _want_ to write what Andy wanted to write. I think the assignment and test together are two ugly. I would accept a syntax like:

if (var blah=getBlah()) // if implicit test for false/null makes sense


or:

if (var blah=getBlah(); blah!=null)


or possibly some other convenient shorthand.

In C++ it might be possible to make an awful preprocessor hack, something like

#define TRY(var, value) for(auto var = value;var!=null;var=null)

TRY(blah, GetBlah()) {
 // do stuff
}


You mgiht be able to improve the semantics, I'm not sure. I doubt it's worth using, though. You may be able to do something fancier with templates, but it's getting it to act like an "if" statement that's hard.

Date: 2011-06-20 07:56 pm (UTC)
From: [identity profile] momentsmusicaux.livejournal.com
But the second version is so ugly! You can't as easily see what's going.

Date: 2011-06-20 08:15 pm (UTC)
From: [identity profile] momentsmusicaux.livejournal.com
I like this in perl:

$saveme = $boring or $interesting;

$boring gets skipped if it gets evaluated as false in some way or other.

Apparently PHP now has this as:

$saveme = $boring ?: $interesting;

which... urgh.

Date: 2011-06-20 08:46 pm (UTC)
From: [identity profile] call-waiting.livejournal.com
Yes, in C++ you can say:

if (blahType blah = GetBlah()) { ... }

Date: 2011-06-20 08:53 pm (UTC)
From: [identity profile] call-waiting.livejournal.com
There's tons of stuff like this you can do in perl; but a lot of it is hard to read. If you pick an idiom and stick to it, you can get away with it though.

One of my favourites over the years has been something along the lines of:

my $result = $cache-<{$key} ||= (...);


...which assigns to $result using a cache of result values: if $result->{$key} exists and evaluates true (as strings do), it just assigns from the hashref dereference. If the hash doesn't contain a value for $key, the (...) code is evaluated, its result assigned to $cache->{$key} and to $result.

Page 1 of 3 << [1] [2] [3] >>

May 2026

S M T W T F S
      1 2
3 45 6 7 8 9
10 11 1213 14 15 16
17181920212223
24252627282930
31      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 17th, 2026 02:07 am
Powered by Dreamwidth Studios