Call by Result

G

Gene Wirchenko

Gene Wirchenko said:
I wish to call by result with a method.
[snip]

http://en.wikipedia.org/wiki/Evaluation_strategy

Did you all knew this before you answered? The reference
has to be /uninitialized/ for an evaluation strategy to be
called "call by result"!

The various call types are not exotic. If you do not know COLD
the terms call-by-reference, call-by-value, call-by-result, and
call-by-value-result (also known as copy-restore), you have a bit of
studying to do. Well, call-by-name is somewhat exotic, but it is
thought to have been a bit of an accident.
But in Java we cannot pass uninitialized references!

A weakness. My UNfavourite Java compilation error message is
that the variable might not have been initialised in code where it
does not matter.
Especially, in this case, the reference is not uninitialized.

I have to do that to kowtow to Java.

[snip]

Sincerely,

Gene Wirchenko
 
G

Gene Wirchenko

[...]
But I was able to look it up in an online encyclopedia:

»When the reference is passed to the callee
uninitialized, this evaluation strategy may
be called "call by result".«

http://en.wikipedia.org/wiki/Evaluation_strategy

Did you all knew this before you answered? The reference
has to be /uninitialized/ for an evaluation strategy to be
called "call by result"!

Maybe that's true technically. But the OP's code initializes the
variable before calling the method. I think it's just as likely that
he's not using the term precisely as defined in your reference, and that
all of the answers do get to the heart of what he's _really_ asking.

Java requires initialisation.
That is, it seems more likely that what the OP cares about is the
"modify the argument, return a boolean" aspect more than he cares about
the "was the argument initialized" aspect.

Yes.

Sincerely,

Gene Wirchenko
 
G

Gene Wirchenko

Ok, the OP contained:


For my taste, the object-oriented way to do this is:

final Getter getter = new Getter();
getter.get();
if( getter.isValid() )result = getter.value(); else ...

, while the Java way to do this is

try{ s = getString(); }
catch( final Exception exception )...

I care about getting the job done. I use OOP when it is
appropriate and do not use it when it is not appropriate.
. The OP used upper-case names of variables and methods,
so he might be a beginner in Java, in which case it might be
more appropriate for him to learn how things are natively
done in Java than to learn how to emulate features of other
languages (such as call by result) in Java.

I am also someone who has been programming professionally for
about twenty-five years. In that time, I have worked out conventions
across different languages for variable-naming.

Sincerely,

Gene Wirchenko
 
G

Gene Wirchenko

On 10/06/2011 07:03, Gene Wirchenko wrote:
[snip]
I am writing a simple preprocessor. I have a few spots where a
string needs to be parsed. I want to call something like this:
String ReturnString="";
boolean DidItWork=GetString(ReturnString);
if (!DidItWork)
// too bad
It is not acceptable to have a special String value mean failure. I
want the method to be able to return any potential string.
I think Stephan Ram's answer is roughly what I would do.

String returnString;
Thagomizor thangomizor = new Thagomizor();
thangomizor.thangomize();
if (!thangomizor.didItWork()) {
throw new TooBadException();
} else {
returnString = thangomizor.getString();
}

Lengthy code (compared with what it could be) to no additional
benefit.

Sincerely,

Gene Wirchenko
 
S

Steven Simpson

I am writing a simple preprocessor. I have a few spots where a
string needs to be parsed. I want to call something like this:
String ReturnString="";
boolean DidItWork=GetString(ReturnString);
if (!DidItWork)
// too bad

I don't think the following suggestion has been covered exactly. Split
GetString() into two methods: the first testing for the string, storing
it in the containing class, and returning true or false; the second
simply retrieving the last string.

I'm assuming that GetString is non-static for this.

class Parser {
/**
* Attempt to parse a string. If successful, the result
* is obtained from {@link #getLastString()}.
*
* @return true if a string was parsed
*/
public boolean parseString() { ... }
public String getLastString() { ... }
}

if (parser.parseString()) {
doSomethingWith(parser.getLastString());
}
 
A

Andreas Leitgeb

Gene Wirchenko said:
2) instead of the string, pass a mutable container of a string:
String[] stringContainer = new String[1];
boolean didItWork = getString(stringContainer);
if (didItWork) { /* stringContainer[0] has the string */ }

This is a kludge but fairly simple. I did a bit more looking and found
http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html
where a simple class is created. I ended up with

I think "kludge" is not the apt term for mine. "hack" may be a better.
As you pointed out already, it is equivalent to creating such a container-
class, but there's just the tradeoff:
- accept some ugliness with "[0]"
- add yet another trivial class to your project or to
your library's whole interface.
Maybe I'm a bad Java-programmer, myself, because I'd go for first,
unless there is some domain-related meaning to such a container
class, like e.g. "FooState" which would then likely contain more
than just one field.
I have used a number of languages. One of the things that I
dislike about Java is the small letter first style. It is
particularly bothersome, because my variable naming convention often
has HN-like prefixes.

So, actually the method here would be named sGetString(), that's fine
with Java's *case*-conventions (but perhaps not with others...)
 
A

Abu Yahya

On 6/11/2011 8:37 PM, Andreas Leitgeb wrote>
So, actually the method here would be named sGetString(), that's fine
with Java's *case*-conventions (but perhaps not with others...)

What does the initial "s" signify here?
 
S

Stefan Ram

For my taste, the object-oriented way to do this is:
final Getter getter = new Getter();
getter.get();
if( getter.isValid() )result = getter.value(); else ...

Trehinking about this again, the object-oriented way to do
this is now (»lambda« and »java.lang.Report« are not part of
Java 6, but hypothetical):

new StringGetter().get
( lambda( final java.lang.String string ){ ... },
lambda( final java.lang.Report report ){ ... });

To understand this, one has to remember that in an
object-oriented language, blocks of code also are objects
(»everything is an object«). »get« would be defined so as to
call its first argument with the value read upon success, or
otherwise call its second argument with an error report upon
failure.

Without static types and with some hypothetical syntax
this becomes:

new StringGetter().get( [string|...], [report|...] );

This is just the realization of »Tell, Don't Ask«.
Here, one asks the object:

if( getter.isValid() )...

. Here, one tells the object what to do:

new StringGetter().get( [string|...], [report|...] );
 
A

Andreas Leitgeb

Martin Gregorie said:
I think its because GW is using a variant of the so-called Hungarian
Notation which AFAIK is a Microsoft invention, initially applied to C and
C++.
The idea is to make the name of a function or method document the type of
object it returns by prefixing the name with an alphabet soup of
initials, so a function returning a string might be called
sMyFunction(). The catch with it is that, if you need to change the type
of the returned value, you need to change all references to it as well,

I wouldn't exactly call that a "catch". If you change the return type
of a method, you'd f...ing better have a look at all call-sites ;-)
At least, the compiler will help you, if it finds old sGetString() still
referenced somewhere. Without changing the name along with the return-
type, you *might* not notice all calls, and end up with a runtime-crash.

There's an entirely different catch, however, namely that people might
change the type but *not* the name, and you end up with the same trouble
as without HN, except wrong expectations on seeing sGetString() which
maybe has been changed to return an Integer.
 
A

Andreas Leitgeb

Stefan Ram said:
This is just the realization of »Tell, Don't Ask«.
Here, one asks the object:
if( getter.isValid() )...
Here, one tells the object what to do:
new StringGetter().get( [string|...], [report|...] );

If you'd like coding like that, you *might* like Tcl.

Passing scriptlets to commands to have them executed (conditionally,
repeatedly, deferredly, just later, within a different context, ...)
is just simply normal in Tcl. Even the "if" statement itself is
merely a command that gets passed scriptlets and executes one (or maybe
even none - if no condition is true and no "else"-scriptlet given) ...
 
W

Wojtek

Gene Wirchenko wrote :
Lengthy code (compared with what it could be) to no additional
benefit.

The benefit is that it is instantly recognizable by any competent Java
programmer as to what it does and how any problem is handled.

If you want minimal source code size, then Java is not for you.
 
W

Wojtek

Gene Wirchenko wrote :
I am also someone who has been programming professionally for
about twenty-five years. In that time, I have worked out conventions
across different languages for variable-naming.

So have I (30 years actually, ah I can see retirement from here...).
And I have had training and/or self-taught in over 15 languages. Shrug,
so what.

However I religiously use the conventions of the language I am writing
in. Amongst other things it allows future maintenance programmers to
read the code without needing to do mental gymnastics to convert code
style before they can understand what the code is doing.

This is important if you ever work in a professional environment. Your
code WILL be looked at by someone else sometime in the future.

The lone programmer (consultant or hired) writing obfuscated code to
their own personal style/standards would not be tolerated in any of the
companies I have worked for.
 
M

Martin Gregorie

I wouldn't exactly call that a "catch". If you change the return type
of a method, you'd f...ing better have a look at all call-sites ;-) At
least, the compiler will help you, if it finds old sGetString() still
referenced somewhere. Without changing the name along with the return-
type, you *might* not notice all calls, and end up with a runtime-crash.
Depends what you're doing. I agree if you, say, are changing the return
value from int to long int, but if you change from returning a string
value to returning a pointer to an internally allocated string, then the
amount of un-necessary work can be quite large.
There's an entirely different catch, however, namely that people might
change the type but *not* the name, and you end up with the same trouble
as without HN, except wrong expectations on seeing sGetString() which
maybe has been changed to return an Integer.
Yes, agreed. I've seen that too.

My other objection is three-fold: HN is ugly, it tends to obscure the
meaning if a function name, and it goes against Kernighan & Pike's naming
recommendations in "The Practise of Programming", which IMO is essential
reading for any fledgling programmers regardless of the language they are
using.

IIRC the original MS C compilers (along with other pre-ANSI C compilers,
I should add) weren't nearly as good as their rivals, such as Borland C,
so I've always wondered if the use of HN was introduced as a way of
forcing the programmer cover for compiler deficiencies in reporting data
type mismatches.
 
M

Martin Gregorie

The lone programmer (consultant or hired) writing obfuscated code to
their own personal style/standards would not be tolerated in any of the
companies I have worked for.
Unfortunately, I've seen a bit much of that, ranging from the idiotic:

- an entire COBOL system written with data names of the form NN999 where,
e.g. NN was MT for all data names in all the mag.tape files used by a
program and 999 ran sequentially from MT001 for the first tape, MT002
for the first record MT003 for the first field in the first record....
and IIRC field and record names could and did differ between programs.
The same was done in PROCEDURE DIVISION except that the paragraph names
were no longer sequential.

to

- a lone contractor by the name of Ken Eagle who called any additional
numeric data names KEN1, KEN2,... and any strings EAGLE1, EAGLE2,...

This was all a long time also hopefully it would no longer happen.
However, as the competence of management doesn't seem to have improved
much over the years, I wouldn't hold my breath.
 
A

Andreas Leitgeb

Peter Duniho said:
In Hungarian, a function would never ever be named "sMyFunction". It
might be named something like "StrMyFunction" or "SzMyFunction" or
"PstMyFunction", etc. depending on the actual return type.

The only "difference" seems to be the multichar type prefix and that
the prefix starts with uppercase letter. Did I miss something?
I guess, even the "Sz" is just the Hungarian(language) version of a
plain "S"(which in Hungarian language would be pronounced like "sh"
if not followed by a "z").

I doubt, that the original HN would have essentially more fans than
the MS-variant.
[...]
There are legitimate reasons to decide to use a naming convention other
than Hungarian, but the question of renaming functions isn't among them.

100% agree
 
M

markspace

I guess, even the "Sz" is just the Hungarian(language) version of a
plain "S"(which in Hungarian language would be pronounced like "sh"
if not followed by a "z").


"Sz" iirc indicates that the string is zero terminated. Yes, Hungarian
notation is that fine grained.
 
A

Andreas Leitgeb

Arved Sandstrom said:
In effect Maybe and Option
are wrapper types just like BoolStr in your example; it's simply that
Scala and Haskell have better language support for dealing with
datatypes of that sort.

Yeah, I hoped you'd give a short example of use in Haskell/Scala, to show
what a language could make even simpler about that.
 
A

Arved Sandstrom

On Fri, 10 Jun 2011 08:23:17 -0300, Arved Sandstrom

[snip]
This is the kind of thing where "purists" will get a bit bloody. Not to

Let them scream. I have other comments elsethread. In short, if
your favourite way of doing things causes me a bunch of extra work to
use, I am liable to not use it.
teach you or any other respondent here how to suck eggs, but I'll throw
in, for general edification of a wider audience, the information that
we've got this problem both because Java has "pass object reference by
value" and Strings are immutable. Hence the OP's question.

Nope. I simply want to call by result.

I know what you said you wanted, Gene. The above chunk of mine that you
quoted provides some context, for the use of any readers who might not
be completely up to speed Java-wise, as to what *any* approach would
have to contend with.

Read a bit more carefully. Thanks.
I based my answer on #2.


Well, imperative programming does exist, and I use it.

So does everyone. A large percentage, maybe even the majority, of Java
code is imperative.
Nope. Too complicated.

String resultString = null;
try {
resultString = GetString(stringToBeParsed);
} catch (Exception e) {
// too bad
}

is more complicated than what you asked for? Go figure.
Get real! It is common in examples to have a comment indicating
what would be done when said code is not particularly relevant to the
example.

What _are_ you talking about, Gene? Don't be so defensive and prickly.

I know that that commented out code isn't particularly relevant to the
example...or more precisely, _you_ don't think it is. That doesn't mean
I can't make a point about the code that would possibly be there, and
how that fits in with exceptions.

Here's a clue, Gene. For someone who supposedly has been on Usenet
forever, here's something that you obviously never picked up: when
people answer other peoples' posts, they are often not just replying to
the one person, they may be speaking to a wider audience, and phrasing
things accordingly.

AHS
 
M

Martin Gregorie

Whatever you might think of Hungarian notation _or_ Microsoft, since it
was invented by Charles Simonyi _before_ he ever was entertaining the
idea of being a Microsoft employee, it is ridiculous to suggest that the
convention was invented in order to gloss over "deficiencies" in
Microsoft's compiler, real or imagined.
I wasn't pointing the finger exclusively at MS - a lot of the early K&R C
compilers were awful and were certainly deficient in type matching,
especially for pointer types. Remember, this was the era when almost all
C compilers consisted of a control program and four separate subsidiary
programs: macro-processor, C to assembler translator, assembler and
linker. They often had to be that way because of current memory sizes.

The first versions of MS C dated from that era, so it would be surprising
if they didn't suffer from the same deficiencies. However, I admit that I
still don't see any reason for introducing Hungarian notation except as a
workround for the lack of rigour in the early compilers.

Context: at that point, 1983/4, I taught myself C on 6809 boxes - Windrush
C on a box with 48K RAM. The first halfway decent C I used was Microware's
K&R flavour for OS-09/68K (which I still use from time to time). It was
some time later that I started to use Borland C, with its excruciating
four memory models plus near and far pointers and non-standard 'standard
libraries', on a DOS box before moving to the Windows version with WfW
3.11. The first really good C I met was the DEC VAX flavour - and IIRC
that was still K&R rather than ANSI.
 
S

Silvio

Yeah, I hoped you'd give a short example of use in Haskell/Scala, to show
what a language could make even simpler about that.

Well, here is an example in Scala:

Let's assume we have a getString defined as:

def getString(s : String) : Option[String] =
{
if (s.reverse == s) Some(s.toLowerCase)
else None
}

then it will return either Some(r) where r is a String or it will return
None indicating failure.

We could call it like this:

val t : Option[String] = getString(s)

or a bit shorter:

val t = getString(s)

and let the compiler figure out the type of t (I could have dropped the
Option[String] return type from the getString definition the same way).

Now we could use pattern matching against t:

t match
{
case Some(r) => println("Success, return value is: " + r)
case None => println("Failure")
}

However, since an Option[T] is a monad like most containers in Scala are
we have shorthand notations for chaining operations on it like map,
foreach, forall, exists etc.

Example1: t.map(_.length) will return an Option[Int] which is None if t
is None or Some(r.length) if t is Some(r)

Example2: t.foreach(println(_)) will print r if t is Some(r) and do
nothing if t is None.

Pattern matching is an incredible powerfull and flexible language
feature in Scala and clearly lays out how Option[T] can be treated. In
practice we rarely use it on an Option because the shorthand notations
cover almost every practical use.

Gr. Silvio
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top