Toward Terser Java


R

Roedy Green

I find this pattern occurs repeatedly:

String quotation = accumulatedQuotation.toFinalString();
if ( quotation.length() > 0 )
{
addToken( new StringLiteralToken( quotation ) );
}



String comment = accumulatedComment.toFinalString();
if ( coment.length() > 0 )
{
addToken( new CommentLiteralToken( comment ) );
}

Note how only the source and the name of the constructor changes.
I can't figure out an elegant way to encapsulate the length test in
addToken.


I woud like to wring something terse like this:

addToken( accumulatedQuotation, StringLiteralToken );
addToken( accumulatedComment, CommentToken );


Any hints on getting this code shorter?


My best idea so far is to pass CommentToken.class as a parameter, use
newInstance, cast to an interface, then give my tokes all default no
parm constructor and setters fill in the information after
construction with the setters.

Is there any more direct way?

Maybe there is a way by giving it a example object to clone.

Maybe I am just being too stingy. I should create the object whether
it has 0 length or not, then discard it later. That offends me since
the constructors have asserts to prevent creation of bad objects.


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
Ad

Advertisements

A

Andrea Desole

Roedy said:
My best idea so far is to pass CommentToken.class as a parameter, use
newInstance, cast to an interface, then give my tokes all default no
parm constructor and setters fill in the information after
construction with the setters.

Is there any more direct way?

a factory class as parameter?
 
T

Thomas Weidenfeller

Roedy said:
I find this pattern occurs repeatedly:

String quotation = accumulatedQuotation.toFinalString();
if ( quotation.length() > 0 )
{
addToken( new StringLiteralToken( quotation ) );
}



String comment = accumulatedComment.toFinalString();
if ( coment.length() > 0 )
{
addToken( new CommentLiteralToken( comment ) );
}

Note how only the source and the name of the constructor changes.
I can't figure out an elegant way to encapsulate the length test in
addToken.

Well, if accumulatedQuotation and accumulatedComment are of different
types, then something like this could do:

-------------------------------------------------------------------
public abstract class BaseAccumulator {

public void addAsTokenTo(SomeClass caller) {
String s = toFinalString();
if(s.length() > 0) {
caller.addToken(createToken(s));
}
}

protected abstract BaseToken createToken(String s);

public String toFinalString() { ... }
}

public class QuotationAccumulator extends BaseAccumulator {
// create matching token
protected BaseToken createToken(s) {
return new StringLiteralToken(s);
}
}

public class CommentAccumulator extends BaseAccumulator {
// create matching token
protected BaseToken createToken(s) {
return new CommentLiteralToken(s);
}
}


public class SomeClass {
public void addToken(BaseToken t) { ... }

public void someMethod() {

accumulatedQuotation.addAsTokenTo(this);
accumulatedComment.addAsTokenTo(this);
}
}
-------------------------------------------------------------------


If this is not the case, you could try something like this, which is
still ugly:


-------------------------------------------------------------------
public class TokenAdder /* what a stupid class name ... */ {

public static void addStringLiteralToken(String s
, SomeClass caller) {
if(s.length() > 0) {
caller.addToken(new StringLiteralToken(s));
}
}

public static void addCommentLiteralToken(String s
, SomeClass caller) {
if(s.length() > 0) {
caller.addToken(new CommentLiteralToken(s));
}
}
}


public class SomeClass {
public void addToken(BaseTokenClass t) { ... }

public void someMethod() {
String quotation = accumulatedQuotation.toFinalString();
TokenAdder.addStringLiteralToken(quotation, this);

String comment = accumulatedComment.toFinalString();
TokenAdder.addCommentLiteralToken(comment, this);
}
}
 
R

Roedy Green

a factory class as parameter?

I think that would work well when you had a small and known number of
possible Token classes to manage.

Don't I then have to write a factory method for every Token class?
Then I write many more lines of code than I saved. I did not want to
write a central make-anything factory method since I want to be able
to dynamically add new Parsers and Tokens.

If there is a way I can do it without propagating a lot of code,
great.

Sometimes I just long for C preprocessor macro ability for when Java
won't let you encapsulate patterns without a fight.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
A

Andrea Desole

Roedy said:
I think that would work well when you had a small and known number of
possible Token classes to manage.

Don't I then have to write a factory method for every Token class?

I would rather say a class for every Token class.
Then I write many more lines of code than I saved. I did not want to
write a central make-anything factory method since I want to be able
to dynamically add new Parsers and Tokens.

I understand. On the other side it is necessary to implement somehow the
creation logic somewhere
If there is a way I can do it without propagating a lot of code,
great.

mmm, the only solution I can think of are generics, supposing you are
using 1.5. I never used generics in Java (still using 1.4.2), so I can't
go any further, but I think that with C++ templates it should be possible.
Something like a template factory class, or a template addToken method.
 
T

Tor Iver Wilhelmsen

Roedy Green said:
addToken( accumulatedQuotation, StringLiteralToken );
addToken( accumulatedComment, CommentToken );

Use reflection for the constructor:

public void addToken(IAccumulated object, Class clazz) {
String quotation = object.toFinalString(); // Interface method
if ( quotation.length() > 0 ) // Interface method
{
addToken( clazz.getConstructor(new Class[] { String.class })
.invoke(new Object[] { quotation }) );
}

}

addToken( accumulatedQuotation, StringLiteralToken.class );
addToken( accumulatedComment, CommentToken.class );

Or use a factory method instead of reflection perhaps.

One of the strengths of the JavaBean model is that you always know
there is a no-parameters constructor, so you can use newInstance(),
which can (retroactively) be thought of as a shortcut for

getConstructor(new Class[0]).invoke(new Object[0])
 
Ad

Advertisements

B

Boudewijn Dijkstra

If there is a way I can do it without propagating a lot of code,
great.

mmm, the only solution I can think of are generics, supposing you are using
1.5. I never used generics in Java [...]

But I have. Generics are not very useful, because of the so-called type
erasure feature. You would still need two parameters and reflection.
Although you can make it type-safe by appending <? extends Token> or <?
extends LiteralToken> to the Class parameter in Tor's example.
 
R

Roedy Green

I understand. On the other side it is necessary to implement somehow the
creation logic somewhere

The way I see it the Token constructor has the right to check the
parameters and abort the construction process with an exception in
order to prevent the creation of a malformed Token.

That is the business of the Token and, by nesting your token classes,
you only have to write such code once and invoke it in only one place.


Think of it as like a walled city with many guarded gates surrounding
the king's palace with only one gate. To protect your king, it is
best to put your effort on the gate in the inner wall. You might
forget to man one of the outer gates.


On the other hand the Token has no business knowing anything about
what collections it is added to. That sort of logic does not belong
in the Token, and in my case I have need of keeping the Tokens as
lightweight as possible since I export them, the decision whether to
add belongs in the code controlling what goes into the container. It
is the one making the decision to avoid creating Tokens with empty
strings. In a few cases it IS ok. This is not an error, so I don't
think it should be handled by an exception.

Just what is it about his pattern that makes it so resistant to simple
encapsulation in a method of the caller or the container?

if ( s.length() != 0 )
{
add ( new X ( s ) )
}

Naively you might think you could write something like this:


addOnlyNonEmpty( StringLiteralToken, s );
or

addOnlyNonEmpty( StringLiteralToken.class, s );
or

addOnlyNonEmpty( class StringLiteralToken, s );

and implement it with:

addOnlyNonEmpty( class SimpleToken X , s )
{
if ( s.length() != 0 )
{
add new X( s );
}
}


Where SimpleToken is a subclass of the Tokens that take a single
string argument constructor.

The problem arises because you can't pass classes as parameters, only
a generic class reference without subtypes which is all but useless
without run-time dynamic reflection.


Because you can't specify the facts Which class to construct, you
can't delegate the construction to the callee.

I wonder how difficult it would be for some future Java to permit
this. It may have many more uses that just saving me writing an if
sandwich around every call invocation.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Raymond DeCampo

Roedy said:
I find this pattern occurs repeatedly:

String quotation = accumulatedQuotation.toFinalString();
if ( quotation.length() > 0 )
{
addToken( new StringLiteralToken( quotation ) );
}



String comment = accumulatedComment.toFinalString();
if ( coment.length() > 0 )
{
addToken( new CommentLiteralToken( comment ) );
}

Note how only the source and the name of the constructor changes.
I can't figure out an elegant way to encapsulate the length test in
addToken.


I woud like to wring something terse like this:

addToken( accumulatedQuotation, StringLiteralToken );
addToken( accumulatedComment, CommentToken );


Any hints on getting this code shorter?


My best idea so far is to pass CommentToken.class as a parameter, use
newInstance, cast to an interface, then give my tokes all default no
parm constructor and setters fill in the information after
construction with the setters.

Is there any more direct way?

Maybe there is a way by giving it a example object to clone.

Maybe I am just being too stingy. I should create the object whether
it has 0 length or not, then discard it later. That offends me since
the constructors have asserts to prevent creation of bad objects.

Roedy,

You don't give us a lot of context here. Perhaps the problem is that
you have specialized too soon. That is, if you could have a generic
accumulator that spits back strings, then check the length of the
string, abort if 0, now determine which token to instantiate. But
perhaps this doesn't fit, we do not have enough information to know.

HTH,
Ray
 
R

Roedy Green

The problem arises because you can't pass classes as parameters, only
a generic class reference without subtypes which is all but useless
without run-time dynamic reflection.

If Java were a person, here would be its political opinion.

Child abandonment ( dropping all references to objects you create) is
perfectly ok.

A fetus (partly constructed object) has the right to abort itself
prior to birth (throw an exception), but not to commit suicide,
(delete itself). It has no say in whether it is conceived in the first
place. (It cannot be interrogated prior to construction.)

Parents may not delegate the process of child creation by sperm or egg
donation. There is no way to get a method to create an object for you
where you supply the class as a parameter)

You cannot know ahead of time if your fetus will live to term. (There
are no constructor preconditions).







--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
L

Lasse Reichstein Nielsen

Roedy Green said:
Parents may not delegate the process of child creation by sperm or egg
donation. There is no way to get a method to create an object for you
where you supply the class as a parameter)

As Java grew old, it became pragmatic and compromised its political
opinion, hence Class#newInstance().

/L
 
Ad

Advertisements

R

Roedy Green

You don't give us a lot of context here. Perhaps the problem is that
you have specialized too soon. That is, if you could have a generic
accumulator that spits back strings, then check the length of the
string, abort if 0, now determine which token to instantiate. But
perhaps this doesn't fit, we do not have enough information to know.

I am not looking for a solution just to this particular question. I
wanted to explore this class of problem where you want encapsulate the
creation of objects. I run into it all the time. This was just a
simple example.

But to explain the context. I am redesigning my Tokens and Parsers
used for JDisplay. see
http://mindprod.com/projects/javapresenter.html
for the big picture.

My token is for rendering petty text. You might look on at as compiled
HTML. A token typically contains some text to render. It has methods
for rendering raw, as CSS HTML, or using my Token rendering Applet.
The tokens themselves have almost no data but some text. All the
rendering information is in the Class static and instance methods
which don't get serialised along the data.

Tokens know nothing about parsing, only about rendering. They know
fonts, CSS classes, point sizes, colours, font families preferences
etc.

A Tokenizer is a sort of crude Java or Bat compile that breaks the
text of a bat file or a Java source code file into word-sized chunks,
and identifies them well enough to colourise them. The Java parser is
smart enough to tell constants from vars from methods from package
names, from definitions and references. It uses a very crude scheme
that work even on incomplete or erroneous programs.

A parser's job is to create an array of tokens out of some text so
that it can be rendered by HTML, or by my mindless rendering applet
that understands no syntax at all. It just renders each token by
calling its methods.

For example a StringLiteral Token, used in displaying Java source
code, contains the characters between "..." not including the end "
marker. It regenerates them on demand. When parsingo "" is legit. so
the text inside could be 0 length.

However say a VarName token, contains the name of a java variable. It
is not allowed to have 0 length. The parser wants to avoid creating
such tokens. It just comes out in the wash that the finite state
automaton from time to time might say "we now have a complete variable
name". Unfortunately, it might have zero length, e.g. a programmer
error or just an artifact of my parser. It is not a bug. I just have
to check before adding the Token.

I could create such useless tokens, then prune the list later of ones
that would not render anything.

For example, implement a method isUseless() that each token implements
to tell if rendered that nothing would happen. You could then remove
pointess tokens at the end or just after they had been created before
being added. I just can't find an easy way to short circuit before
construction.

That may be the cleanest way to handle my current particular problem
since the Token, more than the parser knows if it is pointless.

It could also be more general than check checking the string for zero
length.


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
A

Andrea Desole

Lasse said:
As Java grew old, it became pragmatic and compromised its political
opinion, hence Class#newInstance().

that's correct, specially if you accept runtime errors.
I would rather find errors at compile time, but that doesn't seem
possible without writing some extra code.
 
S

Stefan Schulz

I find this pattern occurs repeatedly:

String quotation = accumulatedQuotation.toFinalString();
if ( quotation.length() > 0 )
{
addToken( new StringLiteralToken( quotation ) );
}



String comment = accumulatedComment.toFinalString();
if ( coment.length() > 0 )
{
addToken( new CommentLiteralToken( comment ) );
}

Note how only the source and the name of the constructor changes.
I can't figure out an elegant way to encapsulate the length test in
addToken.


I woud like to wring something terse like this:

addToken( accumulatedQuotation, StringLiteralToken );
addToken( accumulatedComment, CommentToken );

Why not just do something like this:

interface TokenCreator {
Token create();
}

TokenCreator stringMaker = new StringLiteralCreator();
TokenCreator commentMaker = new CommentCreator();
// both implement TokenCreator

addToken(accumulatedComment, commentMaker);

where addToken performs the check, and calls the TokenCreators create
method?
 
R

Roedy Green

TokenCreator stringMaker = new StringLiteralCreator();
TokenCreator commentMaker = new CommentCreator();
// both implement TokenCreator

addToken(accumulatedComment, commentMaker);

I see it works, but I think I am somewhat further behind in terseness.
Recall I was just trying to save one line of code adding the token.

To avoid this, it looks as if I have had to write a dozen more lines
per token class.


What if Interfaces were extended to permit the specification of
constructors and static methods?

you could the use constructors and static methods given only the
interface reference.



then you might be able to write code like this using an example object
that implements the interface:

void adder ( AnyTokenInterfaceExexemplar a , String value )
{
if ( value != 0 )
{
AnyTokenInterface b = a.new ( value );
add ( b );
}
}

Perhaps the same code could work passing either the name of an class
implementing the interface or an example object implementing that
interface.

The basic idea is you should be able to pass class objects around with
the same sort of inheritance as you pass objects around as parameters.

Static methods would then override in much the same way instance
methods do.

The class object should give you access to the class features of the
base class, same way objects work. The distinction between objects
and classes would blur. new should be not be treated so specially, and
be accessible easily once you have a class object.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
K

Kevin McMurtrie

Roedy Green said:
I find this pattern occurs repeatedly:

String quotation = accumulatedQuotation.toFinalString();
if ( quotation.length() > 0 )
{
addToken( new StringLiteralToken( quotation ) );
}



String comment = accumulatedComment.toFinalString();
if ( coment.length() > 0 )
{
addToken( new CommentLiteralToken( comment ) );
}

Note how only the source and the name of the constructor changes.
I can't figure out an elegant way to encapsulate the length test in
addToken.


I woud like to wring something terse like this:

addToken( accumulatedQuotation, StringLiteralToken );
addToken( accumulatedComment, CommentToken );


Any hints on getting this code shorter?


My best idea so far is to pass CommentToken.class as a parameter, use
newInstance, cast to an interface, then give my tokes all default no
parm constructor and setters fill in the information after
construction with the setters.

Is there any more direct way?

Maybe there is a way by giving it a example object to clone.

Maybe I am just being too stingy. I should create the object whether
it has 0 length or not, then discard it later. That offends me since
the constructors have asserts to prevent creation of bad objects.

It sounds like your code is suffering from cumbersome objects. Smarten
them up so they're easier to use.


public interface IAccumulatedQuotation
{
public int length();
public StringLiteralToken toStringLiteralToken();
}

public interface IAccumulatedComment
{
public int length();
public CommentLiteralToken toCommentLiteralToken();
}


. . .

addToken (IAccumulatedQuotation aq)
{
addToken(aq.toStringLiteralToken());
}

addToken (IAccumulatedComment ac)
{
addToken(ac.toCommentLiteralToken());
}


. . .

IAccumulatedQuotation accumulatedQuotation= ...
IAccumulatedComment accumulatedComment= ...

if (accumulatedQuotation.length() > 0)
addToken(accumulatedQuotation);

if (accumulatedComment.length() > 0)
addToken(accumulatedComment);
 
Ad

Advertisements

R

Roedy Green

IAccumulatedQuotation accumulatedQuotation= ...
IAccumulatedComment accumulatedComment= ...

if (accumulatedQuotation.length() > 0)
addToken(accumulatedQuotation);

That does not make any sense. I have added more code to each of the
dozens of Token classes to have one line in the calling. In the end I
write more code.

It would only make sense if I used these objects in many different
contexts that could make use of those smarts.


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
K

Kevin McMurtrie

Roedy Green said:
That does not make any sense. I have added more code to each of the
dozens of Token classes to have one line in the calling. In the end I
write more code.

It would only make sense if I used these objects in many different
contexts that could make use of those smarts.

Is there a base class for the tokenizers? That's where generic
convenience methods would go.
 
R

Roedy Green

Is there a base class for the tokenizers? That's where generic
convenience methods would go.

Exactly. The catch in that code can't do any sort of generic
construction, even for subclasses that all implement that same
constructor.

this is what blocks putting the code where it belongs with only one
copy of it.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
Ad

Advertisements

T

Tim Tyler

Roedy Green said:
Sometimes I just long for C preprocessor macro ability for when Java
won't let you encapsulate patterns without a fight.

That really was bad, though. At least these days machines can
read and write source code - and do some editing tasks for us.

The preprocessor was one of the things that made that *very*
challenging to do properly in C/C++.
 

Top