Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concepts adjustments #552

Merged
merged 10 commits into from
Sep 2, 2023
Merged

Concepts adjustments #552

merged 10 commits into from
Sep 2, 2023

Conversation

vnkmpf
Copy link
Contributor

@vnkmpf vnkmpf commented Aug 28, 2023

Some more changes than simply typos.
I structured the changes in different commits for better review.

Copy link
Collaborator

@neenjaw neenjaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @vnkmpf, I appreciate the typo, grammar and link updates. The addition of type hints and visibility modifiers though should all be removed.

The reason is because the concept exercises are specifically designed to be as simple as possible at the start. Minimal magic keywords. Each exercise then builds on the last adding one new thing (ideally) at each step.

concepts/class-basics/about.md Outdated Show resolved Hide resolved
concepts/class-basics/about.md Outdated Show resolved Hide resolved
@@ -21,4 +21,4 @@ foreach (iterable as &$value) {
unset($value);
```

However, `$value` persists after the `foreach` block so it is **strongly** recommended to break the reference using `unset($value)` after the block.
However, `$value` persists after the `foreach` block so it is **strongly** recommended to use key access instead of a reference or to break the reference using `unset($value)` after the block.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this change. Please give me some context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are recommendations* not to use explicit references in PHP code.
By explicit I mean using the & character. Implicit references would be functions like sort or passing objects as parameters.

Here, speaking of foreach, it would be using:

foreach ($list as $key => $item) {
    $list[$key] = doSomething($item);
}

instead of

foreach ($list as &$item) {
    $item = doSomething($item);
}

While it's more verbose, it's less error-prone.

    • I am not sure I can find them now, if you want some sources. I read them years ago when we had heated debates at work :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have also read some posts referencing similar things, but they tend to lack very good references. I think we do need to reference t sort of points though if we can.

I thought we might be over losing that sentence, the thoughts are related but maybe it needs a code example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added code examples and re-phrased.
Commit pushed for review.

Because it's only mentioned how to solve the problem, and not recommended to avoid them, wouldn't it be somewhat advanced topic for PHP newcomers? Also with not-highly-authoritative source, more like someone's blog or StackOverflow?
I mean a special nuance, moreover inside foreach-concept.

Copy link
Contributor

@MichaelBunker MichaelBunker Aug 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the track wants to avoid having students use this feature of the language, it should be omitted entirely and if not it probably deserves a separate section given the potential for misunderstanding. I don't necessarily agree with the idea that passing by reference shouldn't be used in PHP. There are times with large variables, or perhaps some sorting functions, where it feels OK to use. I do think it can complicate code quickly though.

If the goal of concepts is to introduce small modular pieces of information about the language that build up to fluency, I think the concept feels out of place in the README here. Passing variables by ref/value should be it's own section, if the track wants to discuss it, instead of just casually tied to this specific type of loop. It's not a simple concept for beginners to understand (or me) and should probably be expanded on. For example there are important differences between PHP references and pointers from other languages, the manual even goes so far as to explicitly say 'references are not like C pointers'.

A few things with the current wording that are a bit confusing.

  • is it makes it seem like passing the loop iterator as a reference &$value is what makes it so that variable exists after the loop is done and therefore users should call unset(). That isn't the case however, as if you do a loop without the reference, the variable will still be defined.
  • It's also not clear why it's strongly recommended to unset the variable. I don't see the need to always unset the variable so perhaps that reason can be expanded here.
  • The README before changes is talking about modifying the existing array in the outer-scope context, the changes here are talking about returning a new object that is different from the array that is being iterated over even though the code sample still shows a pass-by-reference. These things aren't the same behavior, which is why this text change is confusing. It should either be something that is taught by the track and included, or it should be omitted. The proposed change is trying to do both and it's going to be confusing for students. In other words, if the track is not going to recommend passing by reference in foreach loops, just don't include it at all. There is way too much cruft in the language and history of PHP for the track to point out all of the not-recommended ways students could write PHP.
<?php

$values = [1,2,3];

foreach ($values as $value) {
  $value++;
}
var_dump($value); // outputs 4 and is defined despite not being defined as a reference variable in the loop

Behavior isn't straightforward to understand for references either. For example, setting a reference to another variable (even if it's another reference), and then unsetting that variable, doesn't result in the reference content being destroyed.

<?php

$values = [3];

foreach ($values as &$value) {
    $value++;
    $temp =& $value; // set a new reference to the current loop iteration.
}
var_dump($value); // 4
var_dump($temp); // 4
unset($value);
// It would be easy for someone to assume that unset is deleting the data the references is pointing to
// and expect this next line to be undefined.
var_dump($temp); // 4 
var_dump($value); // undefined variable warning

All this is to say that passing by reference can be complicated and consider adding a separate section for it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MichaelBunker I agree, that with those examples, the document is more about references than foreach loops.
And that it's a big topic in itself. I would vote to omit it entirely here.

When it comes to a concept about references, I would omit that too. As you very correctly pointed out

There is way too much cruft in the language and history of PHP for the track to point out all of the not-recommended ways students could write PHP.

I feel the same about stuff like $$$$var or goto. I wouldn't really teach it, because I don't think it should be used in modern PHP, it's somewhat controversial in PHP and "because you can, doesn't mean you should".


There are times with large variables, or perhaps some sorting functions

I read that it doesn't save memory or perform faster. I think the original source was this SO post

I tried to measure myself, and if I'm not doing something wrong, references are really slower and more memory expensive (PHP 8.2, array size: 10_000_000).
I wonder whether references in native functions like sort add any benefit. Maybe because they are in C, not PHP?


Even if there are use cases where they add performance gains, I still wouldn't teach them in a beginner tutorial because:

  • their behavior is confusing,
  • people confuse them with C when hearing "reference",
  • they can lead to unexpected rewriting of variables,
  • if they optimize special edge cases - it's not a beginner topic.

Considering Michael's answer and the first paragraphs:
Is everybody OK with removing the reference section from this document?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, can agree with that, I have similar views about references from my experience

concepts/type-declaration/about.md Outdated Show resolved Hide resolved
- `null` cannot be used as a standalone type, but types may be declared _nullable_ by either using `?Type` or `Type1|Type2|null`.
- `false` cannot be used as a standalone type, and is included for historical reasons, as many legacy functions may return `false` when an error is encountered.
- `null` cannot be used as a standalone type, but types may be declared _nullable_ by either using `?Type` or `Type1|Type2|null`. As of [PHP 8.2](https://www.php.net/manual/en/language.types.declarations.php), null can be used as a standalone type.
- `false` cannot be used as a standalone type, and is included for historical reasons, as many legacy functions may return `false` when an error is encountered. As of [PHP 8.2](https://www.php.net/manual/en/language.types.declarations.php) false can be used as a standalone type.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reword this whole sentence point. It reads disjointed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I was thinking how to reword it, I came to this question.
Do the parts saying null and false cannot be used as a standalone type still make sense?
PHP 8.0 will stop getting security updates this November.
PHP 8.1 will stop being actively supported this November.

I hope I understand correctly what the standalone type means in this context.

Here is an example online:
https://onlinephp.io?s=PY5BCoMwFETXFbxDFgUV3Gh3tba0B-gVJCaxBmIS4k9BqnevP4q7mff_MHN72N4SLpiiTqQjOMmggcmKsS6yKo7iqPOagTSadMakUsOsvVLkLLX1kF0JRvRn7qgaRRz94ujkBHinyUCB9STdHwleTiFa30nyNq3hU5IjLAJ5KsnEBsoAXqbdLBcd9QoQhhaEyzptwXVf6hruB5uuEAdiQ5bvpjhUeagLqqz6Aw%2C%2C&v=8.2.9

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I don't disagree with your point. I think the track should be kept as up to date as possible. This is one of the earlier concepts I wrote I think before 8.2 was confirmed. I would be good to invert the content completely

Maybe something like:

false and null can be used as standalone types, first introduced in php 8.2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got an impression it's soon to be outdated and maybe it's a good idea to remove the mention of them not being standalone types.

Commit pushed for review.

@vnkmpf
Copy link
Contributor Author

vnkmpf commented Aug 29, 2023

Thanks for review @neenjaw
I reverted what you requested.

I explained one comment and I have a question about another one.

* rephrase
* code examples
* remove mention of false not being a standalone type
* remove the mention for null, keep nullable text
* based on GH discussion
* set exercism name instead of github
@vnkmpf vnkmpf requested a review from neenjaw September 1, 2023 10:59
@neenjaw
Copy link
Collaborator

neenjaw commented Sep 2, 2023

Looks good, thanks this work.

@neenjaw neenjaw merged commit 2ec1240 into exercism:main Sep 2, 2023
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants