- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Since I didn't find any part of the standard stating out sequence of judging parallel conditions, I would like to ask if anyone has even met the situation like:
function Test(str) implicit none character(*), intent(in) :: str if(LEN(str) >=2 .AND. str(2:2) == 's')then ! do something... end if end function Test
In the if statement above, there are two conditions. If the dummy argument str we passed in was just a single character assume 'a', there is going to be an error with ivf compiler as condition str(2:2)=='s' is referring to index number 2 of 'a' which simply doesn't exist. So in Fortran, is it true that conditions within a judging statement are all be judged every time of execution ? In other words no left-to-right judging sequence ? About this case I See difference in C# while since condition LEN(str)>=2 is false, the if block will be skipped and, no matter true or false the second condition is, it is not ever judged so it's legal to write these conditions together, but not in Fortran. Appreciate any explanation.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran and C/C++/C# have different rules for expression evaluation. Fortran allows the compiler to evaluate any logically equivalent expression to any degree of completeness. There is no strict left-to-right nor short-circuiting. It's a classic error Fortran programmers have made for decades - sometimes it works the way they want and they think that's what the language says, and then they change compilers or even versions and the order changes.
The correct solution is to use nested IF-THEN.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This goes to the often discussed topic of "short-circuit evaluation". There are a number of posts in our Fortran forums discussing what compilers are permitted to do within the Standard.
To your questions, no not all conditions are judged at execution and no left-to-right evaluation is guaranteed. Refer to Dr. Fortran and "The Dog That Did Not Bark"
Here's a couple of other posts that offer related discussion and details.
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/499227
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/282534
(Posting although I see the Doctor himself has replied - Thank you Steve!)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you do not like (want) nested IF-THEN blocks, then write an Fortran acceptable IF statement
if(LEN(str) >=2 .AND. str(MIN(LEN(str),2):MIN(LEN(str),2)) == 's') then
But then I think you will agree that nested IF-THEN blocks will be clearer (and faster).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A solution is to create a specific function that will make the code clearer. For example something like that:
logical*4 function test_2nd_char(str,char) character(*), intent(in) :: str,char test_2nd_char=.false. if (len(str).le.2) return if (str(2:2).ne.char(1:1)) return test_2nd_char=.true. end function if (test_2nd_char(str,"s")) .....
Or more generic :
logical*4 function match(str,pattern) character(*), intent(in) :: str,pattern match=.false. if (len(str).lt.len(pattern)) return do i=1,len(pattern) if (pattern(i:i).ne."*".and.str(i:i).ne.pattern(i:i)) return enddo match=.true. end function if (match(str,"*s")) .....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please don't use nonstandard syntax such as "logical*4". Just "logical" would work fine here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Ret.) wrote:
Please don't use nonstandard syntax such as "logical*4". Just "logical" would work fine here.
Indeed; I would also suggest anyone considering any such "special" functions should first review what the Fortran standard offers as intrinsic procedures; INDEX, SCAN, VERIFY in this instance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Effectively,
if (index(str,"s").eq.2) ...
will do the job.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Vautier, Gilles wrote:
Effectively,
if (index(str,"s").eq.2) ...will do the job.
That's a very good solution on this case, thanks a lot.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Vautier, Gilles wrote:
Effectively,
if (index(str,"s").eq.2) ...will do the job.
@Vautier, Gilles,
"will do the job" - how? What if str is "ss"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Blane J. wrote:
Quote:
Vautier, Gilles wrote:
Effectively,
if (index(str,"s").eq.2) ...will do the job.
That's a very good solution on this case, thanks a lot.
@Blane J.,
Did you check how your expected IF construct would function if you followed Steve's correct advice in Message #2 versus what you would get if you follow this latest one with the INDEX intrinsic? What should happen if str equals "ss"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan wrote:
What should happen if str equals "ss"?
So the best solution is to write a user function.as I show in a precedent post.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
LOL. Like many things in programming there are many possible solutions, in this case the 'best' solution probably depends if this test is done in lots of places or just one, in the former case my personal preference would be a user function (less code easier to maintain), in the latter case a nest IF as it is more immediately apparent what the program logic is without having to find a and look at a function.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
or...
module mod_test contains logical function Test(str) implicit none character(*), intent(in) :: str Test = .false. ; if(LEN(str) >=2) Test = (str(2:2) == 's') end function Test end module mod_test program ifif use mod_test implicit none print *, Test('x') print *, Test('xx') print *, Test('xs') end program ifif
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan wrote:
@Blane J.,
Did you check how your expected IF construct would function if you followed Steve's correct advice in Message #2 versus what you would get if you follow this latest one with the INDEX intrinsic? What should happen if str equals "ss"?
Oops, that's a problem. so as suggested, a user function to handle the evaluation process should be the best anyway, thanks all again above.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page