2

Is it possible to create a function with a "for loop" style syntax? And if so, what would that style of function be called?

For example a for loop follows this syntax:

for(i = 0; i < 10; i++)
{
    //do something
}

Is it possible in any language to create your own function, for example, called "myFunction" that could be called like this:

myFunction(x; y; z)
{
   //do something
}

(Notice the semicolons instead of commas for the function inputs and then the block wrapper)

Normally in programming languages you can only create a function and call it like this:

myFunction(input1, input2, input2);

So basically I want to be able to create a function that accepts inputs, separated by semicolons and a block of code in the same way that a for loop does. Is this possible? What is this called?

Edit - CLARIFICATION: I'm not looking to write a shortcut function that runs a loop. I'm looking to write a made up function, that from a syntax standpoint, looks like a for loop. However, the made up function will never ever call "for" or for any reason.

Edit - Would this be possible to implement at the "compiler" level? I understand the closest thing in JavaScript would be the following (but it isn't as clean as a for):

myFunction(x, y, z, function()
{
    //do something
});
7
  • 3
    "no, you cannot do that"... Commented May 1, 2013 at 15:05
  • You've tagged two different programming languages. Which one are you asking about? Commented May 1, 2013 at 15:10
  • 1
    If you can explain why exactly you want to do this, it's possible people might have some alternate suggestions. Commented May 1, 2013 at 15:20
  • while you can't do that, you can use [].map to iterate with a private scope. Commented May 1, 2013 at 16:28
  • @squint both languages Commented May 1, 2013 at 16:39

5 Answers 5

3

Well... as you already said: you can create your own methods, but you cannot create keywords. for is such a keyword and keywords do not have to comply to normale rules which methods do.

The closest thing I can think of is this:

void MyForLoop<T>(Func<T> myInitialization, Func<T, bool> myCondition, Func<T, T> myIteration, Action<T> myBody)
{
   // Check the arguments for null's.
    T iterator = myInitialization();
    while(myCondition(iterator))
    {
         myBody(value);
         value = myIteration(value);
    }
}

You can call it like:

MyForLoop(() => 0, i => i < 10, i => i + 1, i => Console.WriteLine(i));
Sign up to request clarification or add additional context in comments.

2 Comments

Is it possible at to write a function that accepts a block like using(var thing=value){//block} or switch(varname){//block}
Sort of... I suggest you post that question again so we can answer it seperate from this question.
1
+50

You are looking to create a new DSL (Domain Specific Language). Java, python, javascript and other languages do have support for this to varying extents. A DSL can sometimes involve special syntax like what you'd like to do with the semicolons, or it can be as simple as the ability to write a really nice API (think jQuery). JavaScript does not support the custom syntax, but the language is really expressive and it is easy to create an api that reads like english.

That being said, you could go ahead and write your code the way you want then run it through some sort of a parser and convert it. You should look at coffeescript's source. You essentially need to be familiar with writing your own language, creating a grammar, parsing things into a syntax tree and the translating code.

Like I said, other languages do have support for creating your own syntax/DSL. Here are some resources:
- http://www.slideshare.net/Siddhi/creating-domain-specific-languages-in-python
- http://www.jetbrains.com/mps/

Personally, I think anytime you have customized syntax it gets extremely confusing for new people working on the project. However, maybe it makes sense for what you are doing.

Comments

0

Your exact syntax isn't possible in JavaScript, but the intent of what you want is. What you want is very similar to forEach provided on Array in modern browsers.

function myLooper(iterations, callback) {
    for(var i = 0; i < iterations; ++i) {
        callback(i);
    }
}

myLooper(4, function(i) {
    console.log(i);
});

// outputs
// 0
// 1
// 2
// 3

here is a fiddle for the above.

and since you also tagged this with C#, here is a C# version:

void MyLooper(int iterations, Action<int> action) {
    for(int i = 0; i < iterations; ++i) {
        action.Invoke(i);
    }
 }

I don't have a C# environment handy right now, so the above is possibly not quite correct.

Comments

0

you ask for a solution in c#, if something in f# (afaik these languages can be used "together") is appreciated as well, then I can offer you the following snippets (note that the separation is not with semicolons as you wished, but with spaces):

The function yourLoop takes three arguments two ints: lowerBound upperBound and a function (with side effects more specifically of type 'a -> unit): body with the meaning that

yourLoop (lowerBound:int) upperBound body

has the same effect as

for i in lowerBound..upperBound do
  body(i)

The function looks as follows:

let rec yourLoop (lowerBound:int) upperBound body =
  if (lowerBound >= upperBound) then body upperBound
  else
    body lowerBound
    yourLoop (lowerBound+1) upperBound body 

for example let this be the body of some method

let something i = printfn "%s%i" "do something with " i

then applying

yourLoop 0 5 something

yields

do something with 0
do something with 1
do something with 2
do something with 3
do something with 4
do something with 5

Similarly, if you want to loop top down instead, then you can write

let rec yourInvertedLoop lowerBound upperBound body =
  if (lowerBound >= upperBound) then body lowerBound
  else
    body upperBound
    yourInvertedLoop (lowerBound) (upperBound-1) body

yielding

yourInvertedLoop 0 5 something

do something with 5
do something with 4
do something with 3
do something with 2
do something with 1
do something with 0

For a more generic function, consider

let rec yourLoopIncr lowerBound upperBound next body =
  if (next lowerBound >= upperBound) then body lowerBound
  else
    body lowerBound
    yourLoopIncr (next lowerBound) upperBound next body 

where you can specify how your loop iterates. for example,

yourLoopIncr 1 25 (fun x-> 2*x) something

will produce

do something with 1
do something with 2
do something with 4
do something with 8
do something with 16

Remark: Note that this solution only works for bodies that don't return values. Of course you can still write stuff on the console or mutate variables and the like. For example will the code

let mutable x = 0
let somethingElse n = x <- x+n 
yourLoop 0 10 somethingElse

set x to the value 55.

Comments

0

You want the function to accept inputs separated by semicolons, why not join your inputs into one string separated by semicolons! If this makes sense to you, then simply have all the inputs in an array and do a .join(';') on the array. Or just pass the array itself, if semicolons are not your specific requirement.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.