Another idea

Hi all,

When thinking of posting this idea I already feel Adam’s or Sean’s breath in
my neck and reminding me of what stupid idea I might come up with.

The following code snippet is something I do very often:

This is just sudo code.

string function something(required struct stConfig) {

        local.stTmp = arguments.stConfig.fileConfig.init;

        stTmp.initPath = "/";

        stTmp.initTimeStamp = true;

        stTmp.initUseCounter = request.fileConfig.counter + 1;

}

The code really doesn’t make sense and I know one can write it by setting an
inline struct like this:

arguments.stConfig.fileConfig.init = {

                    initPath: "/", 

                    initTimeStamp: true, 

                    initUseCounter: request.fileConfig.counter + 1

        }; 

But that is not the idea here. What I do in order to speed up the runtime
(and not having to resolve a multi-level struct is time consuming) and
readability (you can’t tell me that this is easier to read:

arguments.stConfig.fileConfig.init.initPath = “/”;

arguments.stConfig.fileConfig.init.initTimeStamp = true;

arguments.stConfig.fileConfig.init.initUseCounter =
request.fileConfig.counter + 1;

)

I tend to assign a long hierarchy of subkeys to a temporary variable (stTmp)
and then use only that one. But this seems kind of odd. So I remembered the
good old Delphi and GFABasic days where one could write a statement like
this:

with variable do {

        .key = something;

}

What would you think of the following code instead of the above:

string function something(required struct stConfig) {

        with(arguments.stConfig.fileConfig.init) {

                    .initPath = "/";

                    .initTimeStamp = true;

                    .initUseCounter = request.fileConfig.counter + 1;

}

}

Or somehow similar. That would immediately speed up the execution and the
writing of the code.

Hi all,

When thinking of posting this idea I already feel Adam’s or Sean’s breath
in my neck and reminding me of what stupid idea I might come up with.

Personal attack, Gert!

;-)On Saturday, 28 February 2015 06:10:06 UTC+13, Gert Franz wrote:


Adam

I personally don’t like Basic nor Delphi (though they bring up nice
memories from my youth…), so I prefer to use inline structs for that
and am unlikely to use such constructs. but before I answer your
question I must first ask another:

arguments.stConfig.fileConfig.init = { ... }

would replace the object that init points to with a new one, thus
discarding any other keys that are not set in the new assignment.

what would this construct do?
with(arguments.stConfig.fileConfig.init) {
.initPath = “/”;
.initTimeStamp = true;
.initUseCounter = request.fileConfig.counter + 1;
}

in other words, let’s say that before the assignment the init key points
to a struct with the key “uniqueId”. the inline construct will lose
it. the original construct (the one you’re trying to avoid) will keep
it. what would the new construct do?

Igal Sapir
Lucee Core Developer
Lucee.org http://lucee.org/On 2/27/2015 9:09 AM, Gert Franz wrote:

Hi all,

When thinking of posting this idea I already feel Adam’s or Sean’s
breath in my neck and reminding me of what stupid idea I might come up
with.

The following code snippet is something I do very often:

This is just sudo code.

string function something(required struct stConfig) {

        local.stTmp = arguments.stConfig.fileConfig.init;

        stTmp.initPath = "/";

        stTmp.initTimeStamp = true;

        stTmp.initUseCounter = request.fileConfig.counter + 1;

}

The code really doesn’t make sense and I know one can write it by
setting an inline struct like this:

arguments.stConfig.fileConfig.init = {

                    initPath: "/",

                    initTimeStamp: true,

                    initUseCounter: request.fileConfig.counter + 1

        };

But that is not the idea here. What I do in order to speed up the
runtime (and not having to resolve a multi-level struct is time
consuming) and readability (you can’t tell me that this is easier to read:

arguments.stConfig.fileConfig.init.initPath = “/”;

arguments.stConfig.fileConfig.init.initTimeStamp = true;

arguments.stConfig.fileConfig.init.initUseCounter =
request.fileConfig.counter + 1;

)

I tend to assign a long hierarchy of subkeys to a temporary variable
(stTmp) and then use only that one. But this seems kind of odd. So I
remembered the good old Delphi and GFABasic days where one could write
a statement like this:

with variable do {

        .key = something;

}

What would you think of the following code instead of the above:

string function something(required struct stConfig) {

        with(arguments.stConfig.fileConfig.init) {

                    .initPath = "/";

                    .initTimeStamp = true;

                    .initUseCounter = request.fileConfig.counter + 1;

}

}

Or somehow similar. That would immediately speed up the execution and
the writing of the code.


You received this message because you are subscribed to the Google
Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to lucee+unsubscribe@googlegroups.com
mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com
mailto:lucee@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/016001d052b0%24380ca960%24a825fc20%24%40lucee.org
https://groups.google.com/d/msgid/lucee/016001d052b0%24380ca960%24a825fc20%24%40lucee.org?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout.

correct. true is the default for overwriteFlag so no need to specify it.

Igal Sapir
Lucee Core Developer
Lucee.org http://lucee.org/On 2/27/2015 10:55 AM, Abram Adams wrote:

So it would be another way to represent:

|
arguments.strConfig.fileConfig.init.append({
initPath: “/”,
initTimeStamp: true,
initUseCounter: request.fileConfig.counter + 1
},true);
|

Correct? So this would be a kind of “map” function for objects/structs?

I agree with Sean that some research into other language’s choice to
include/exclude from the language.

Interesting idea, just trying to wrap my head around use case.

On Friday, February 27, 2015 at 10:37:22 AM UTC-8, Gert Franz wrote:

Well it is just a shorthand notation to the following. And yes I
agree that assigning a {} would replace the construct so it is
unusable. But this code would be identical:

 

arguments.stConfig.fileConfig.init.initPath = "/";
arguments.stConfig.fileConfig.init.initTimeStamp = true;

arguments.stConfig.fileConfig.init.initUseCounter =
request.fileConfig.counter + 1;

and

 

with(arguments.stConfig.fileConfig.init) {

       .initPath = "/";
       .initTimeStamp = true;
       .initUseCounter = request.fileConfig.counter + 1;
}

Sincerely
Gert Franz

 

*RASIA GmbH*

Spittelgasse 7

5103 Moeriken-Wildegg

Email: @Gert_Franz <javascript:>
Skype: gert.franz

Phone Switzerland: +41 76 5680 231

 

*Von:*lu...@googlegroups.com <javascript:>
[mailto:lu...@googlegroups.com <javascript:>] *Im Auftrag von
*Igal @ Lucee.org
*Gesendet:* Freitag, 27. Februar 2015 18:42
*An:* lu...@googlegroups.com <javascript:>
*Betreff:* Re: [Lucee] Another idea

 

also, would the proposed construct result in an atomic operation
(like the inline struct) or not (like the original construct)?

Igal Sapir
Lucee Core Developer
Lucee.org <http://lucee.org/>

On 2/27/2015 9:21 AM, Igal @ Lucee.org wrote:

    I personally don't like Basic nor Delphi (though they bring up
    nice memories from my youth...), so I prefer to use inline
    structs for that and am unlikely to use such constructs.  but
    before I answer your question I must first ask another:

        arguments.stConfig.fileConfig.init = { ... }
    would replace the object that init points to with a new one,
    thus discarding any other keys that are not set in the new
    assignment.

    what would this construct do?
        with(arguments.stConfig.fileConfig.init) {
           .initPath = "/";
           .initTimeStamp = true;
           .initUseCounter = request.fileConfig.counter + 1;
    }

    in other words, let's say that before the assignment the init
    key points to a struct with the key "uniqueId".  the inline
    construct will lose it.  the original construct (the one
    you're trying to avoid) will keep it.  what would the new
    construct do?

    Igal Sapir
    Lucee Core Developer
    Lucee.org <http://lucee.org/>

    On 2/27/2015 9:09 AM, Gert Franz wrote:

        Hi all,

         

        When thinking of posting this idea I already feel Adam’s
        or Sean’s breath in my neck and reminding me of what
        stupid idea I might come up with.

         

        The following code snippet is something I do very often:

         

        This is just sudo code.

        string function something(required struct stConfig) {

                    local.stTmp = arguments.stConfig.fileConfig.init;

                    stTmp.initPath = "/";

                    stTmp.initTimeStamp = true;

                    stTmp.initUseCounter =
        request.fileConfig.counter + 1;

        }

         

        The code really doesn’t make sense and I know one can
        write it by setting an inline struct like this:

         

        arguments.stConfig.fileConfig.init = {

                                initPath: "/",

                                initTimeStamp: true,

                                initUseCounter:
        request.fileConfig.counter + 1

                    };

         

        But that is not the idea here. What I do in order to speed
        up the runtime (and not having to resolve a multi-level
        struct is time consuming) and readability (you can’t tell
        me that this is easier to read:

         

        arguments.stConfig.fileConfig.init.initPath = "/";

        arguments.stConfig.fileConfig.init.initTimeStamp = true;

        arguments.stConfig.fileConfig.init.initUseCounter =
        request.fileConfig.counter + 1;

         

        )

        I tend to assign a long hierarchy of subkeys to a
        temporary variable (stTmp) and then use only that one. But
        this seems kind of odd. So I remembered the good old
        Delphi and GFABasic days where one could write a statement
        like this:

         

        with variable do {

                    .key = something;

        }

         

        What would you think of the following code instead of the
        above:

         

        string function something(required struct stConfig) {

                    with(arguments.stConfig.fileConfig.init) {

                                .initPath = "/";

                                .initTimeStamp = true;

                                .initUseCounter =
        request.fileConfig.counter + 1;

        }

        }

         

        Or somehow similar. That would immediately speed up the
        execution and the writing of the code.

        -- 
        You received this message because you are subscribed to
        the Google Groups "Lucee" group.
        To unsubscribe from this group and stop receiving emails
        from it, send an email to lucee+un...@googlegroups.com
        <javascript:>.
        To post to this group, send email to
        lu...@googlegroups.com <javascript:>.
        To view this discussion on the web visit
        https://groups.google.com/d/msgid/lucee/016001d052b0%24380ca960%24a825fc20%24%40lucee.org
        <https://groups.google.com/d/msgid/lucee/016001d052b0%24380ca960%24a825fc20%24%40lucee.org?utm_medium=email&utm_source=footer>.
        For more options, visit https://groups.google.com/d/optout
        <https://groups.google.com/d/optout>.

     

 

-- 
You received this message because you are subscribed to the Google
Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to lucee+un...@googlegroups.com <javascript:>.
To post to this group, send email to lu...@googlegroups.com
<javascript:>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/54F0AC66.9060007%40lucee.org
<https://groups.google.com/d/msgid/lucee/54F0AC66.9060007%40lucee.org?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout
<https://groups.google.com/d/optout>.


You received this message because you are subscribed to the Google
Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to lucee+unsubscribe@googlegroups.com
mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com
mailto:lucee@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/50591358-2423-4ce9-9f2c-2808989ba395%40googlegroups.com
https://groups.google.com/d/msgid/lucee/50591358-2423-4ce9-9f2c-2808989ba395%40googlegroups.com?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout.

In JS I often setup a struct to hold default values then use _extend()
(in node, with client side I use jQuery’s $.extend() method)

in Lucee you can do the “jQuery.extend()” with “.append( required struct,
boolean overwrite=true)”.

Now… brace yourself Igal… I agree.

Gert’s pseudocode:

arguments.stConfig.fileConfig.init = {
initPath: “/”,
initTimeStamp: true,
initUseCounter: request.fileConfig.counter + 1
};

Code possible right now:

arguments.stConfig.fileConfig.init.append({
initPath: “/”,
initTimeStamp: true,
initUseCounter: request.fileConfig.counter + 1
});

I don’t see the need for another syntax construct if this is all the with
construct would afford us.

However there might be other things one could do with a with sort of thing,
so perhaps more / different use cases might help convince me. And also
checking what more modern languages (pref ones similar to how CFScript
generally works so we don’t get more syntactical abominations added to the
language :wink: do in this regard is probably a good suggestion from Sean too.

As an aside, I don’t think adding syntax constructs to work around
performance shortcomings of existing syntax is a good idea, in general.
That sort of thing should not be dealt with at a language level. Language
considerations should generally (I’m falling short of saying “only ever”)
concern themselves with making the coders using that language’s life
easier. It should not be leveraged to make the authors of the language’s
life easier. IE: performance considerations ought to be dealt with under
the hood.On Saturday, 28 February 2015 07:29:47 UTC+13, Igal wrote:


Adam

I wonder if this has us edging closer to the concept of context managers
(e.g., with-open or with-open-file macros in Clojure or Common Lisp, or the
with keyword and related decorators in Python). I’ve often ended up
creating my own setup and teardown methods within components, auto-running
them, if present, through the use of some kind of factory pattern. A
component or class is much heavier than simple lexical games with a deep
struct, but perhaps it’s worth kicking around some of these ideas. Maybe
the lexical with as proposed could be implemented as a degenerate case of a
context manager, allowing future expansion of the concept as the language
evolves.

Definitely against the leading dots - it’s unnecessarily restrictive to
make this only about setting/calling.

The command should simply set the default container for unscoped
variables (i.e. change it from local scope, or be the first checked if
cascading is enabled).

So then:

Some.Long.Dotted.Struct.Var1  = VarA;
Some.Long.Dotted.Struct.Other = Arguments.Whatever;

becomes:

with Some.Long.Dotted.Struct
{
	Var1  = local.VarA;
	Other = Arguments.Whatever;
}

(Where the scoping of VarA is required when cascading is turned off.)

And this allows adding logic (beyond simple ternary/null-coalescing):

with Some.Long.Dotted.Struct
{
	Var1  = local.VarA;
	Other = Arguments.Whatever?:0;
	
	loop index=local.i item=local.item
	{
		Stuff[local.i] = doSomething(local.item);
		
		if (Stuff[local.i])
			++Other;
	}
}

Of course, there’s a good chance I’d just do that as a function with
Some.Long.Dotted.Struct passed by reference into it, but this seems to
be a potentially convenient bridge between that and the inability of an
inline struct to have a small bit of non-atomic logic.

Setting the default for unscoped variables seems to cater for what Gert
wants, whilst also being a simple concept to understand/explain, and
building upon what the language already has rather than a completely
new thing.

Me personally, I think the idea is great. Groovy already has the concept
of a with closure that you can attach to ANY object to denote context. It
is mostly done for clear context and avoid repetitive assignments,
retrievals and executions. Me personally, I would love to have this same
capability as well in CFML. (Reference:
Groovy Goodness: the With Method - Messages from mrhaki)

Example of how it could be written in CFML:

component accessors=“true”{
property username;
property email;
property labels;

function speakUp() { return "I am $username"; }
function addLabel( required value ){ 
    labels.append( arguments.value ); 
}

}

sample = new Sample()
sample.with {
username = ‘luis’
email = ‘luis@majano.com’
writeOutput( speakUp() )
addLabel( ‘CFML’ )
addLabel( ‘Java’ )
};

sb = new java:StringBuilder();
sb.with {
append( 'Just another way to add ’ )
append( 'strings to the StringBuilder ’ )
append( ‘object.’ )
}On Friday, February 27, 2015 at 9:10:06 AM UTC-8, Gert Franz wrote:

Hi all,

When thinking of posting this idea I already feel Adam’s or Sean’s breath
in my neck and reminding me of what stupid idea I might come up with.

The following code snippet is something I do very often:

This is just sudo code.

string function something(required struct stConfig) {

        local.stTmp = arguments.stConfig.fileConfig.init;

        stTmp.initPath = "/";

        stTmp.initTimeStamp = true;

        stTmp.initUseCounter = request.fileConfig.counter + 1;

}

The code really doesn’t make sense and I know one can write it by setting
an inline struct like this:

arguments.stConfig.fileConfig.init = {

                    initPath: "/", 

                    initTimeStamp: true, 

                    initUseCounter: request.fileConfig.counter + 1

        }; 

But that is not the idea here. What I do in order to speed up the runtime
(and not having to resolve a multi-level struct is time consuming) and
readability (you can’t tell me that this is easier to read:

arguments.stConfig.fileConfig.init.initPath = “/”;

arguments.stConfig.fileConfig.init.initTimeStamp = true;

arguments.stConfig.fileConfig.init.initUseCounter =
request.fileConfig.counter + 1;

)

I tend to assign a long hierarchy of subkeys to a temporary variable
(stTmp) and then use only that one. But this seems kind of odd. So I
remembered the good old Delphi and GFABasic days where one could write a
statement like this:

with variable do {

        .key = something;

}

What would you think of the following code instead of the above:

string function something(required struct stConfig) {

        with(arguments.stConfig.fileConfig.init) {

                    .initPath = "/";

                    .initTimeStamp = true;

                    .initUseCounter = request.fileConfig.counter + 1;

}

}

Or somehow similar. That would immediately speed up the execution and the
writing of the code.

Yes, this construct would be useful when building out large structures. For example, when serializing queries or objects for json output in a custom manner. If you have to do any complex logic during the serialization, then you can’t use inline structs as you build out the hierarchy (because you can’t have any logic). So that forces you to use temporary variables to hold the inner members that get appended to the outers, etc. The larger or more nested the output becomes the more cumbersome this is.

Essentially Gert’s idea is the midway between inline structures and manual procedural structure creation. It allows nested blocks of execution that can contain statements. This would be useful to have when needed.

I’m against it.

They already deprecated the with statement in JS strict mode for good
reasons.

It can get really confusing for human readers especially when they dont
know in which scope of the scope chain the key is.

Let’s have a look at the following example:

function foobar(foo, bar) {
with (bar) {
dump(foo);
}
}

If you forget to define foo in the passed object, you wont get an error but
unexpected results.

According to my opinion we don’t need a completely new statement to achieve
this. How about self executing functions?
They can solve the problem as well:

(function (v) {
dump(v.name.first & " " & v.name.last);
}(variables.foobar.users.user.susi));

You could use this approach multiple ways.

Example of how it could be written in CFML:

All good, except you’re using Groovy closure syntax, not CFML’s.

Groovy:
{arg1, arg2, etc → statements}

CFML:
function(arg1, arg2, etc){ statements}

I think the Groovy approach is OK, and there’s definitely a precedent set
(ie: Groovy does it), but it ought to use CFML syntax:

anyOldObject.with(function(arg1, arg2, etc){
// statements where the anyOldObject is the scopeless context
});

Now if we were having a separate conversation about CFML’s closure syntax
being too wordy, then that’s fine: let’s have that conversation too. But
that’s not part of this conversation. Lets not conflate the two.

Or perhaps rather than having a special with() method which changes the
way scopes are dealt with (which is a bit magical, so not that cool),
instead we augment closure syntax to take an object which becomes the
“this” context:

(function(arg1, arg2, etc) with (anyOldObject) {
this.someProperty = newValue; // equiv to setting
anyOldObject.someProperty
}))();

I’ve also added in IIFE
http://en.wikipedia.org/wiki/Immediately-invoked_function_expression
syntax there, which CFML should have anyhow.

Or perhaps Lucee’s implementation of IIFE syntax should be able to pass in
what “this” should be?

Or, perhaps because “this” is misused in CFML, then referencing “this” like
this is wrong, and the better fit is back to just the “anyOldObject” above
is what’s used for scopeless references. So a hybrid between the magic
Groovy behaviour, but tuned to be more explicit and less magical and
in-keeping with CFML’s parlance:

(function(arg1, arg2, etc) with (anyOldObject) {
someProperty = newValue; // equiv to setting anyOldObject.someProperty
})();

or

(function(arg1, arg2, etc) {
someProperty = newValue; // equiv to setting anyOldObject.someProperty
}, anyOldObject)();

Of these two, I prefer the former as it couples the closure with the
context, rather than the IIFE having the context coupled to it. I can see
arguments both ways though.On Sunday, 1 March 2015 06:52:18 UTC+13, Luis Majano wrote:


Adam