pony-tutorial icon indicating copy to clipboard operation
pony-tutorial copied to clipboard

[3/?] Add ability to run code examples in the playground: Fetch tutorial snippet from URL by file name

Open shaedrich opened this issue 1 year ago • 11 comments

See https://github.com/ponylang/pony-tutorial/issues/340

[!WARNING] Will only work, after #544 has been merged. Works in combination with https://github.com/ponylang/pony-playground/pull/205. Contains changes from #544 until db1eb1183d0746535db719cd537ad8c00a9cc1d1

Example: https://deploy-preview-542--pony-tutorial.netlify.app/getting-started/hello-world#the-code

Open questions

  • ~~What to do with the non-pony files?~~
  • What to do with partial examples that won't run on their own?
  • no Main actor found in package 'main'

Files

Getting Started

  • [x] hello-world-main.pony

Types

  • [ ] classes-swap-values-sugar.pony
  • [ ] classes-swap-values.pony
  • [ ] classes-wombat-constructor-invocation.pony
  • [ ] classes-wombat-constructors.pony
  • [ ] classes-wombat.pony
  • [ ] classes-zero-argument-constructors-invocation.pony
  • [ ] classes-zero-argument-constructors.pony
  • [ ] primitives-doors.pony
  • [ ] actors-behaviors.pony
  • [ ] actors-sequential.pony
  • [ ] traits-and-interfaces-marker-methods.pony
  • [ ] traits-and-interfaces-multiple-traits.pony
  • [ ] traits-and-interfaces-nested-traits.pony
  • [ ] traits-and-interfaces-nominal-and-structural-subtyping.pony
  • [ ] traits-and-interfaces-nominal-subtyping-in-pony.pony
  • [ ] traits-and-interfaces-nominal-subtyping.pony
  • [ ] traits-and-interfaces-open-world-enumerations.pony
  • [ ] traits-and-interfaces-open-world-interface.pony
  • [ ] traits-and-interfaces-open-world-typing.pony
  • [ ] traits-and-interfaces-private-methods.pony
  • [ ] traits-and-interfaces-structural-subtyping-in-pony.pony
  • [ ] traits-and-interfaces-structural-subtyping.pony
  • [ ] traits-and-interfaces-trait.pony
  • [ ] traits-and-interfaces-type-union.pony
  • [ ] structs-constructors.pony
  • [ ] structs-fields.pony
  • [ ] type-aliases-complex-types-interface.pony
  • [ ] type-aliases-complex-types-trait.pony
  • [ ] type-aliases-enumerations-apply.pony
  • [ ] type-aliases-enumerations-iteration.pony
  • [ ] type-aliases-enumerations-namespace.pony
  • [ ] type-aliases-enumerations.pony
  • [ ] type-aliases-hash-set.pony
  • [ ] type-aliases-map.pony
  • [ ] type-aliases-set-is.pony
  • [ ] type-expressions-combined.pony
  • [ ] type-expressions-intersection.pony
  • [ ] type-expressions-tuple-declaration.pony
  • [ ] type-expressions-tuple-destructuring.pony
  • [ ] type-expressions-tuple-direct-access.pony
  • [ ] type-expressions-tuple-reassignment.pony
  • [ ] type-expressions-type-alias.pony
  • [ ] type-expressions-union.pony

Expressions

  • [ ] literals-array-literals.pony
  • [ ] literals-as-expression.pony
  • [ ] literals-character-literals.pony
  • [ ] literals-floats.pony
  • [ ] literals-multi-line-string-literals.pony
  • [ ] literals-multibyte-character-literals.pony
  • [ ] literals-number-types.pony
  • [ ] literals-numeric-typing.pony
  • [ ] literals-string-literals-encoding.pony
  • [ ] literals-string-literals-instances.pony
  • [ ] literals-string-literals.pony
  • [ ] literals-triple-quoted-string-literals.pony
  • [ ] literals-type-inference-coercion.pony
  • [ ] literals-type-inference-reference-capabilities.pony
  • [ ] literals-type-inference-union.pony
  • [ ] variables-fields-constructor-assignment.pony
  • [ ] variables-fields-definition-assignment.pony
  • [ ] variables-fields-implicit-assignment.pony
  • [ ] variables-fields-let-reassignment.pony
  • [ ] variables-let-reassignment.pony
  • [ ] variables-local-variables.pony
  • [ ] variables-scope.pony
  • [ ] variables-var-vs-let.pony
  • [ ] operators-add.pony
  • [ ] operators-infix-operator.pony
  • [ ] operators-operator-aliasing.pony
  • [ ] operators-precedence-infix-and-unary-operators-with-parentheses.pony
  • [ ] operators-precedence-infix-and-unary-operators-without-parentheses.pony
  • [ ] operators-precedence-single-operator.pony
  • [ ] operators-precedence-unary-operator-with-parentheses.pony
  • [ ] operators-precedence-with-parentheses.pony
  • [ ] operators-precedence-without-parentheses.pony
  • [ ] operators-unary-operators.pony
  • [ ] arithmetic-default-integer-arithmetic.pony
  • [ ] arithmetic-explicit-numeric-conversion.pony
  • [ ] arithmetic-partial-and-check-arithmetic.pony
  • [ ] arithmetic-unsafe-conversion.pony
  • [ ] control-structures-conditionals-expression-implicit-none.pony
  • [ ] control-structures-conditionals-expression-union-type.pony
  • [ ] control-structures-conditionals-expressions.pony
  • [ ] control-structures-conditionals-if-else.pony
  • [ ] control-structures-conditionals-if-elseif-else.pony
  • [ ] control-structures-conditionals-if.pony
  • [ ] control-structures-conditionals-nested-if-else.pony
  • [ ] control-structures-iterator-methods.pony
  • [ ] control-structures-loop-expression-else.pony
  • [ ] control-structures-loop-expression-none.pony
  • [ ] control-structures-loop-expression.pony
  • [ ] control-structures-loops-for-while-comparison.pony
  • [ ] control-structures-loops-for.pony
  • [ ] control-structures-loops-repeat.pony
  • [ ] control-structures-loops-while-break-else.pony
  • [ ] control-structures-loops-while.pony
  • [ ] match-expression.pony
  • [ ] match-capabilities-only.pony
  • [ ] match-capabilities.pony
  • [ ] match-captures.pony
  • [ ] match-custom-eq-operand.pony
  • [ ] match-guards.pony
  • [ ] match-tuples-ignore-elements.pony
  • [ ] match-tuples.pony
  • [ ] match-type-and-value.pony
  • [ ] match-value-pattern-matching-vs-type-check.pony
  • [ ] match-values.pony
  • [ ] as-operator-array-literal.pony
  • [ ] as-operator-match-statement-comparison.pony
  • [ ] as-operator-match-statement-without-try.pony
  • [ ] as-operator-more-specific-interface-with-reference-capability.pony
  • [ ] as-operator-more-specific-interface.pony
  • [ ] as-operator-more-specific-type.pony
  • [ ] as-operator-unrelated-type.pony
  • [ ] methods-anonymous-methods.pony
  • [ ] methods-chaining-return-value.pony
  • [ ] methods-chaining.pony
  • [ ] methods-constructors-calling-on-expression.pony
  • [ ] methods-constructors-calling-reuse-variable-name.pony
  • [ ] methods-constructors-calling.pony
  • [ ] methods-constructors.pony
  • [ ] methods-default-arguments.pony
  • [ ] methods-functions-calling-implicit-this.pony
  • [ ] methods-functions-calling.pony
  • [ ] methods-functions.pony
  • [ ] methods-named-and-positional-arguments-combined.pony
  • [ ] methods-named-arguments.pony
  • [ ] errors-dispose-multiple.pony
  • [ ] errors-dispose.pony
  • [ ] errors-partial-functions.pony
  • [ ] errors-try-else.pony
  • [ ] errors-try-then.pony
  • [ ] errors-try-without-else.pony
  • [ ] errors-with-blocks.pony
  • [ ] equality-equatable-default-implementation.pony
  • [ ] equality-identity-equality.pony
  • [ ] equality-primitives.pony
  • [ ] equality-structural-equality.pony
  • [ ] sugar-apply-explicit.pony
  • [ ] sugar-apply-implicit.pony
  • [ ] sugar-apply-with-arguments-explicit.pony
  • [ ] sugar-apply-with-arguments-implicit.pony
  • [ ] sugar-create-apply-combined-explicit.pony
  • [ ] sugar-create-apply-combined-implicit.pony
  • [ ] sugar-create-explicit.pony
  • [ ] sugar-create-implicit.pony
  • [ ] sugar-create-with-arguments-explicit.pony
  • [ ] sugar-create-with-arguments-implicit.pony
  • [ ] sugar-update-additional-parameters.pony
  • [ ] sugar-update-explicit.pony
  • [ ] sugar-update-implicit.pony
  • [ ] object-literals-actor-literal.pony
  • [ ] object-literals-closing-over-values.pony
  • [ ] object-literals-fields-assignment.pony
  • [ ] object-literals-lambda-as-explicit-object-literal.pony
  • [ ] object-literals-lambda-capture-and-rename-values.pony
  • [ ] object-literals-lambda-capture-values.pony
  • [ ] object-literals-lambda-reference-capabilities-2.pony
  • [ ] object-literals-lambda-reference-capabilities.pony
  • [ ] object-literals-lambda-with-reference-capability-as-explicit-object-literal.pony
  • [ ] object-literals-lambda-with-reference-capability.pony
  • [ ] object-literals-lambda.pony
  • [ ] object-literals-object-literal-with-interface.pony
  • [ ] object-literals-object-literal.pony
  • [ ] object-literals-reference-capability.pony
  • [ ] partial-application-callback-function-with-all-arguments-bound.pony
  • [ ] partial-application-callback-function-with-no-arguments-bound.pony
  • [ ] partial-application-callback-function-with-out-of-order-arguments.pony
  • [ ] partial-application-callback-function-with-some-arguments-bound.pony
  • [ ] partial-application-partially-applying-a-partial-application.pony

Reference capabilities

  • [ ] reference-capabilities-constructors-for-different-capabilities.pony
  • [ ] reference-capabilities-default-vs-explicit.pony
  • [ ] reference-capabilities-string-capabilities.pony
  • [ ] reference-capabilities-string-default.pony
  • [ ] reference-capability-specificy-a-capability-other-than-the-default.pony
  • [ ] consume-and-destructive-read-consuming-a-variable-and-change-its-reference-capability.pony
  • [ ] consume-and-destructive-read-consuming-a-variable.pony
  • [ ] consume-and-destructive-read-moving-a-value.pony
  • [ ] recovering-capabilities-format-int.pony
  • [ ] recovering-capabilities-ref-to-iso.pony
  • [ ] recovering-capabilities-string-append.pony
  • [ ] recovering-capabilities-with-explicit-reference-capability.pony
  • [ ] aliasing-alias-types.pony
  • [ ] aliasing-ephemeral-types.pony
  • [ ] aliasing-iso-to-tag.pony
  • [ ] aliasing-multiple-references-to-an-iso-object.pony
  • [ ] aliasing-trn-to-box.pony
  • [ ] arrow-types-box.pony
  • [ ] arrow-types-this.pony
  • [ ] arrow-types-type-parameter.pony

Object capabilities

  • [ ] derived-authority-authority-hierarchies.pony
  • [ ] derived-authority-delegating-and-restricting-authority.pony
  • [ ] derived-authority-restrict-then-delegate-your-authority.pony

Generics

  • [ ] generics-and-reference-capabilities-accept-any-reference-capability.pony
  • [ ] generics-and-reference-capabilities-capability-generic-class.pony
  • [ ] generics-and-reference-capabilities-default-capability-and-constraint.pony
  • [ ] generics-and-reference-capabilities-explicit-constraint-and-default-capability.pony
  • [ ] generics-and-reference-capabilities-foo-iso-consume-iso-constructor-parameter.pony
  • [ ] generics-and-reference-capabilities-foo-iso-consume-iso-function-parameter.pony
  • [ ] generics-and-reference-capabilities-foo-iso.pony
  • [ ] generics-and-reference-capabilities-foo-ref-and-this-ref.pony
  • [ ] generics-and-reference-capabilities-foo-ref.pony
  • [ ] generic-constraints-foo-any-read.pony
  • [ ] generics-foo-non-generic.pony
  • [ ] generics-foo-string.pony
  • [ ] generics-foo-with-any-val.pony
  • [ ] generics-generic-class-initialization.pony
  • [ ] generics-generic-methods.pony
  • [ ] generics-type-parameter-defaults-definition.pony
  • [ ] generics-type-parameter-defaults-initialization.pony

Packages

  • [ ] use-statement-collections.pony
  • [ ] use-statement-scheme-indicators-optional-package-scheme-specifier.pony
  • [ ] use-statement-scheme-indicators-required-package-scheme-specifier.pony
  • [ ] use-statement-time-now.pony
  • [ ] use-statement-time.pony
  • [ ] use-statement-use-names-conflict.pony
  • [ ] use-statement-use-names-resolution-alternative.pony
  • [ ] use-statement-use-names-resolution.pony

Testing

  • [ ] ponycheck-ponytest-for-all.pony
  • [ ] ponycheck-ponytest.pony
  • [ ] ponycheck-usage-quickcheck.pony
  • [ ] ponycheck-usage.pony
  • [ ] ponytest-aggregation.pony
  • [ ] ponytest-example.pony

C-FFI

  • [ ] c-ffi-callbacks-bare-functions-pass-to-c-api.pony
  • [ ] c-ffi-callbacks-bare-functions.pony
  • [ ] c-ffi-callbacks-bare-lambda-callback.pony
  • [ ] c-ffi-callbacks-bare-lambda-struct.pony
  • [ ] c-ffi-callbacks-sqlite3-callback-2.pony
  • [ ] c-ffi-callbacks-sqlite3-callback.pony
  • [ ] c-abi-jump-consistent-hashing.pony
  • [ ] c-abi-pony-use-native-jump-consistent-hashing-c-implementation.pony
  • [ ] calling-c-access-list-entry-with-explicit-return-type.pony
  • [ ] calling-c-access-list-entry-without-return-type.pony
  • [ ] calling-c-addressof.pony
  • [ ] calling-c-default-method-in-primitive.pony
  • [ ] calling-c-default-method-in-trait.pony
  • [ ] calling-c-different-types-of-lists.pony
  • [ ] calling-c-ffi-functions-raising-errors.pony
  • [ ] calling-c-file-path.pony
  • [ ] calling-c-from-c-struct.pony
  • [ ] calling-c-generic-list.pony
  • [ ] calling-c-ioctl-struct.pony
  • [ ] calling-c-memcpy.pony
  • [ ] calling-c-pointer-to-opaque-c-type.pony
  • [ ] calling-c-type-signature-compatibility.pony
  • [ ] calling-c-variadic-c-functions.pony
  • [ ] calling-c-writev-struct.pony
  • [ ] calling-c-writev-tuple.pony
  • [ ] linking-c-use-lib-foo.pony
  • [ ] linking-c-use-with-condition.pony

Gotchas

  • [ ] divide-by-zero-floats.pony
  • [ ] divide-by-zero-partial.pony
  • [ ] divide-by-zero-unsafe.pony
  • [ ] divide-by-zero.pony
  • [ ] garbage-collection.pony
  • [ ] scheduling.pony
  • [ ] function-call-side-effects.pony
  • [ ] recursion.pony

Appendices

  • [ ] appendices-annotations-empty-with-nosupertype-annotation.pony
  • [ ] appendices-annotations-empty-without-nosupertype-annotation.pony
  • [ ] appendices-annotations-likely-and-unlikely-annotations.pony
  • [ ] appendices-annotations-nodoc-annotation.pony
  • [ ] appendices-annotations-packed-annotation.pony
  • [ ] appendices-annotations-syntax.pony
  • [ ] appendices-examples-access-command-line-arguments.pony
  • [ ] appendices-examples-create-arrays-with-values.pony
  • [ ] appendices-examples-empty-class-functions.pony
  • [ ] appendices-examples-enumeration-with-values-with-namespace.pony
  • [ ] appendices-examples-enumeration-with-values.pony
  • [ ] appendices-examples-iterable-enumerations.pony
  • [ ] appendices-examples-modify-a-lexically-captured-variable-in-a-closure.pony
  • [ ] appendices-examples-operator-overloading.pony
  • [ ] appendices-examples-pass-array-of-values-to-ffi.pony
  • [ ] appendices-examples-test-helper.pony
  • [ ] appendices-examples-use-cli-package-to-parse-command-line-arguments.pony
  • [ ] appendices-examples-write-tests.pony
  • [ ] appendices-platform-dependent-code.pony
  • [ ] appendices-serialization-compare-original-object-with-deserialized-object.pony
  • [ ] appendices-serialization-custom-serialization.pony
  • [ ] appendices-whitespace-comments.pony
  • [ ] appendices-whitespace-do-a-then-do-a-unary-negation-of-b.pony
  • [ ] appendices-whitespace-docstrings.pony
  • [ ] appendices-whitespace-subtract-b-from-a.pony
  • [ ] error-messages-left-side-is-immutable.pony
  • [ ] error-messages-left-side-must-be-something-that-can-be-assigned-to.pony
  • [ ] error-messages-receiver-type-is-not-a-subtype-of-target-type.pony

shaedrich avatar Apr 22 '24 05:04 shaedrich

What to do with the non-pony files?

As discussed in the previous PR, please leave those ones out of the code-samples subdirectory - leave out anything we don't plan to test by compiling.

What to do with partial examples that won't run on their own?

We suggest using the ability to show a partial snippet of a code sample for a given set of lines, so that we can show only the partial example, but the outer code (hidden) would make the file in the code-samples directory compilable.

no Main actor found in package 'main'

The same idea applies - we can put actor Main in one of the hidden lines of the code sample file, outside the partial snippet that is shown.

jemc avatar May 14 '24 18:05 jemc

What to do with partial examples that won't run on their own?

We suggest using the ability to show a partial snippet of a code sample for a given set of lines, so that we can show only the partial example, but the outer code (hidden) would make the file in the code-samples directory compilable.

no Main actor found in package 'main'

The same idea applies - we can put actor Main in one of the hidden lines of the code sample file, outside the partial snippet that is shown.

Would you like this to be addressed here or in #544?

The problem with wrapping every code sample in an actor and calling it is, that it creates a whole lot of boilerplate code. This could possibly be done by the playground instead in https://github.com/ponylang/pony-playground/pull/205

shaedrich avatar May 15 '24 16:05 shaedrich

Okay, I tested an implementation into the playground, and while it is possible to implement, it will a) not work in all cases and b) not be versatile enough to be beneficial. However, I don't think, this should be done in #544, since this will be an additional huge amount of work, as every snippet needs to be tested and additional hidden code parts must be determined, separately. Maybe, this could even be done in another PR to keep track of the changes and their progress. Furthermore, technically, some pending draft PRs could be done in the meantime already, then.

shaedrich avatar May 16 '24 00:05 shaedrich

I don't think wrapping should be done by the playground. Having in sample but only displaying some in tutorial seems appropriate. I'm ok with that being a separate PR.

@jemc thoughts?

SeanTAllen avatar May 16 '24 00:05 SeanTAllen

@SeanTAllen I added said PR just in case and listed my progress there alongside some questions: #545

shaedrich avatar May 20 '24 20:05 shaedrich

Deploy request for pony-tutorial rejected.

Name Link
Latest commit 5787880f00018e84b581d540b3a103e6094e2c99

netlify[bot] avatar May 21 '24 18:05 netlify[bot]

additional huge amount of work, as every snippet needs to be tested and additional hidden code parts must be determined, separately

I don't think the snippets need to be tested in terms of verifying their runtime behavior - that would indeed be a huge amount of work.

We just need to validate that they compile successfully.

This was discussed briefly in the sync call.

jemc avatar Jun 04 '24 18:06 jemc

I don't think the snippets need to be tested in terms of verifying their runtime behavior - that would indeed be a huge amount of work.

We just need to validate that they compile successfully.

Well, if they unexpectedly throw an error in the playground, they are no use. But you'll see that reflected in the PR description and comments in #545

shaedrich avatar Jun 04 '24 18:06 shaedrich

unexpectedly throw an error

They won't throw a compilation error, right? That's what we want to test for, so that should indeed be covered by this work.

If you mean a runtime error, well, in idiomatic Pony (and these samples are definitely supposed to be idiomatic Pony), errors are handled so tightly that nothing really "unexpectedly throws an error" at runtime. What you have at most are flaws in program logic,.

It's not impossible that some breaking change in the compiler would cause a logic bug to appear in a code sample, but the probability should be vanishingly unlikely - that's the worst possible kind of breaking change we could make in the compiler or standard libraries, because it would also have that "subtle logic bug" effect on user-land code. We have an extreme aversion to introducing changes that would cause such "subtle logic bugs" so we take every effort we can to ensure that breaking changes in Pony will "fail loudly" at compile time.

Put all this together with the fact that making all these code samples behavior-testable would be a massive amount of work (likely an order of magnitude or more greater than what you've already done), and I just don't believe it's worth the effort, either for you or for people we're asking to write new tutorial content in the future.

In general, testing the runtime behavior of Pony programs for breaking changes should be done using our "runner tests" in the ponyc repo - it's not really a concern of the tutorial repo.

jemc avatar Jun 04 '24 19:06 jemc

My choice of words might not have been ideal in reflecting technical details, however, what people care at the end of the day is:

  • Tutorial talks about something
  • They encounter a code snippet
  • They click on the button below code snippet
  • Playground: 💥

That's what they will see in some cases while what they expected will be "Hello world". They will feel lied to or at least that nobody bothers if the examples work.

Tutorial users won't necessarily be experts on Pony and might not be able to fix logic errors other contributors committed and nobody checked.

would be a massive amount of work

I've already essentially documented all the expectations in #545 while doing that PR so it's more or less copy and paste. No real additional work to do here.

shaedrich avatar Jun 04 '24 19:06 shaedrich

what people care at the end of the day is:

I agree :+1:

My position is that breaking changes from upstream that cause subtle logic flaws are vanishingly unlikely, so I don't expect that to be a problem in practice. So I think that skipping the work of running the examples (i.e. only compiling them) will still accomplish the goal that "people care at the end of the day", but without the extra burden of needing to create/curate runtime output expectations for every tutorial sample snippet. I think we should only focus on ensuring that the tutorial snippets continue to compile.

jemc avatar Jun 04 '24 22:06 jemc