From 1ff8ec2771c4115b894fa0ee3fc34a499665c93b Mon Sep 17 00:00:00 2001 From: Ryan Kes Date: Wed, 30 Oct 2024 18:27:56 +0100 Subject: [PATCH] Quartz sync: Oct 30, 2024, 6:27 PM --- ...0613170532-variable_types_in_javascript.md | 161 ++++++++ .../20200613170705-operators_in_javascript.md | 27 ++ ...200613170756-javascript_type_conversion.md | 17 + ...613170756-type_conversion_in_javascript.md | 17 + content/wiki/20200613170905-javascript.md | 135 +++++++ .../wiki/20200613170934-javascript_books.md | 14 + .../wiki/20200613171743-javascript_types.md | 84 ++++ ...3172137-binding_variables_in_javascript.md | 46 +++ ...00613172534-control_flows_in_javascript.md | 132 +++++++ ...20200613172534-javascript_control_flows.md | 26 ++ .../20200702203250-bindings_and_scopes.md | 65 ++++ .../wiki/20200702204226-optional_arguments.md | 40 ++ content/wiki/20200702204351-closure.md | 35 ++ content/wiki/20200702204437-recursion.md | 17 + content/wiki/20200704151304-history.md | 25 ++ ...151508-economic_state_of_ussr_1942_1943.md | 77 ++++ content/wiki/20200704151715-economics.md | 8 + content/wiki/20200704151950-ledger.md | 120 ++++++ content/wiki/20200704152249-vocabulary.md | 62 +++ content/wiki/20200704152442-rust.md | 66 ++++ ...0200706161134-stages_of_islamic_history.md | 20 + ...00706164411-stages_of_christian_history.md | 22 ++ content/wiki/20200706165803-the_chaldeans.md | 15 + content/wiki/20200826142641-golang.md | 59 +++ content/wiki/20200826142755-packages.md | 66 ++++ content/wiki/20200826151337-functions.md | 195 ++++++++++ content/wiki/20200826151514-variables.md | 232 +++++++++++ .../20200826151846-flow_control_statements.md | 268 +++++++++++++ content/wiki/20200826191127-tests.md | 205 ++++++++++ content/wiki/20200826191508-tooling.md | 44 +++ content/wiki/20200826201029-arrays.md | 29 ++ content/wiki/20200826201605-objects.md | 16 + content/wiki/20200826201737-mutability.md | 35 ++ .../wiki/20200826201856-object_operators.md | 32 ++ .../wiki/20200826201959-object_functions.md | 19 + .../20200827142818-higher_order_functions.md | 85 ++++ .../wiki/20200827170931-functions_macros.md | 72 ++++ content/wiki/20200827171036-tooling.md | 66 ++++ content/wiki/20200827171318-rust_books.md | 28 ++ .../wiki/20200827171554-variables_in_rust.md | 152 ++++++++ content/wiki/20200827190035-rust_comments.md | 114 ++++++ .../wiki/20200827190443-rust_control_flow.md | 97 +++++ content/wiki/20200828170945-ownership.md | 7 + content/wiki/20200828180957-pointers.md | 53 +++ content/wiki/20200828181259-structs.md | 186 +++++++++ content/wiki/20200828182327-arrays.md | 26 ++ content/wiki/20200828182546-slices.md | 290 ++++++++++++++ content/wiki/20200828192034-maps.md | 126 ++++++ content/wiki/20200831155304-methods.md | 65 ++++ content/wiki/20200831171822-interfaces.md | 179 +++++++++ content/wiki/20200831193417-structs.md | 155 ++++++++ content/wiki/20200901105237-error_handling.md | 11 + content/wiki/20200901141141-goroutines.md | 264 +++++++++++++ content/wiki/20200902150714-enums.md | 263 +++++++++++++ .../20200902162305-regular_expressions.md | 38 ++ content/wiki/20200909202454-errors.md | 57 +++ content/wiki/20200911150451-callbacks.md | 27 ++ content/wiki/20200911154351-promises.md | 39 ++ content/wiki/20200911155947-generators.md | 123 ++++++ content/wiki/20200915140449-vectors.md | 148 +++++++ content/wiki/20200915151358-strings.md | 145 +++++++ content/wiki/20200915153033-hash_maps.md | 137 +++++++ .../20200916162727-unrecoverable_errors.md | 34 ++ .../wiki/20200916163737-recoverable_errors.md | 171 ++++++++ content/wiki/20200916172802-commonjs.md | 31 ++ content/wiki/20200916172914-ecmascript.md | 20 + content/wiki/20200917155644-reflection.md | 9 + content/wiki/20200917161757-generics.md | 135 +++++++ content/wiki/20200917163203-traits.md | 198 ++++++++++ content/wiki/20200918173820-mutex.md | 37 ++ content/wiki/20200918174548-waitgroup.md | 54 +++ content/wiki/20200918180634-rustc.md | 15 + content/wiki/20200918180750-cargo.md | 151 ++++++++ content/wiki/20200918183524-tests.md | 179 +++++++++ content/wiki/20200921154246-context.md | 70 ++++ content/wiki/20200922160850-destructuring.md | 16 + ...20200922162003-parameter_default_values.md | 12 + .../wiki/20200922162127-named_parameters.md | 26 ++ .../wiki/20200922162500-rest_parameters.md | 32 ++ content/wiki/20200922164416-numbers.md | 24 ++ content/wiki/20200922164551-strings.md | 31 ++ content/wiki/20200922164727-booleans.md | 40 ++ content/wiki/20200922164830-empty_values.md | 16 + content/wiki/20200923144022-closures.md | 45 +++ content/wiki/20200923150006-iterators.md | 141 +++++++ content/wiki/20200923153425-number.md | 40 ++ content/wiki/20200923153614-math.md | 43 +++ content/wiki/20200928193245-embedding.md | 47 +++ content/wiki/20200929135609-box_t.md | 86 +++++ content/wiki/20200929141711-deref_trait.md | 109 ++++++ content/wiki/20200929142932-drop_trait.md | 34 ++ content/wiki/20200929145534-rc_t.md | 63 +++ content/wiki/20200929152628-refcell_t.md | 63 +++ .../wiki/20200929161126-basic_annotations.md | 49 +++ content/wiki/20200929161126-typescript.md | 67 ++++ .../wiki/20200929161544-primitive_types.md | 35 ++ content/wiki/20200929162129-arrays.md | 21 + content/wiki/20200929162220-interfaces.md | 40 ++ .../20200929162417-inline_type_annotation.md | 26 ++ .../20200929163051-typescript_generics.md | 60 +++ .../20200929163219-typescript_union_type.md | 20 + ...0929163316-typescript_intersection_type.md | 27 ++ .../20200929163624-typescript_tuple_type.md | 46 +++ .../20200929163825-typescript_type_alias.md | 29 ++ .../20200930105954-ambient_declarations.md | 28 ++ .../wiki/20200930110721-typescript_enums.md | 22 ++ content/wiki/20200930121904-rust_threads.md | 127 ++++++ .../wiki/20200930123003-message_passing.md | 105 +++++ ...930123749-rust_shared_state_concurrency.md | 52 +++ content/wiki/20201001105545-lib_d_ts.md | 49 +++ .../20201001110806-typescript_functions.md | 205 ++++++++++ .../20201001112126-typescript_callable.md | 78 ++++ ...0201002101745-typescript_type_assertion.md | 23 ++ .../20201002102455-typescript_type_guard.md | 23 ++ ...20201002103357-typescript_literal_types.md | 56 +++ content/wiki/20201005171253-readonly.md | 69 ++++ content/wiki/20201006102934-pattern_syntax.md | 365 ++++++++++++++++++ ...111125-javascript_function_declerations.md | 33 ++ .../20201006111244-declaration_notation.md | 28 ++ .../wiki/20201006111349-arrow_functions.md | 41 ++ ...93418-javascript_object_getters_setters.md | 22 ++ .../20201007095614-typescript_never_type.md | 32 ++ ...07101133-typescript_discriminated_union.md | 177 +++++++++ content/wiki/20201008090316-class_notation.md | 38 ++ .../wiki/20201008090449-method_definition.md | 17 + content/wiki/20201008090613-inheritance.md | 39 ++ .../wiki/20201008092225-index_signatures.md | 113 ++++++ ...20201009090331-javascript_array_methods.md | 108 ++++++ ...0331-javascript_array_prototype_methods.md | 26 ++ content/wiki/20201009104050-typescript_4_0.md | 9 + .../wiki/20201009104411-typescript_classes.md | 27 ++ .../wiki/20201012093745-javascript_maps.md | 97 +++++ .../wiki/20201012094248-javascript_sets.md | 18 + .../20201012094749-javascript_weakmaps.md | 46 +++ .../20201014092625-javascript_iterables.md | 26 ++ .../20201014092846-javascript_iterator.md | 41 ++ content/wiki/20201014094144-spread.md | 29 ++ content/wiki/20201021141613-vue_js.md | 13 + .../wiki/20201022094207-javascript_proxies.md | 312 +++++++++++++++ ...201022095438-javascript_metaprogramming.md | 93 +++++ content/wiki/20201023130243-es2016.md | 20 + ...201026103714-javascript_async_functions.md | 39 ++ content/wiki/20201026104538-es2017.md | 46 +++ .../wiki/20201029194838-carthaginian_peace.md | 17 + content/wiki/20201029195142-detritus.md | 10 + content/wiki/20201029195302-useful_idiot.md | 13 + ...20201029195404-intercommunicating_zones.md | 15 + .../wiki/20201029195742-historical_terms.md | 9 + .../wiki/20201029195945-geographic_terms.md | 7 + .../wiki/20201029195945-geographical_terms.md | 7 + .../20201029200040-political_science_terms.md | 7 + content/wiki/20201029200235-podophilia.md | 11 + content/wiki/20201029200327-sexual_terms.md | 7 + content/wiki/20201029201415-bluestocking.md | 11 + content/wiki/20201029204128-gregarious.md | 7 + content/wiki/20201029204304-adjectives.md | 16 + ...0201030092200-javascript_async_iterator.md | 57 +++ .../wiki/20201030093304-javascript_for_of.md | 21 + content/wiki/20201030093404-es6.md | 114 ++++++ .../20201030093832-javascript_if_statement.md | 20 + ...20201030094040-javascript_for_statement.md | 13 + ...01030094138-javascript_switch_statement.md | 51 +++ ...94343-javascript_breaking_out_of_a_loop.md | 16 + .../20201030094749-javascript_comments.md | 16 + content/wiki/20201030095105-es2018.md | 33 ++ .../20201030095741-javascript_for_await_of.md | 48 +++ content/wiki/20201030182939-verbs.md | 8 + content/wiki/20201030183019-geld.md | 14 + content/wiki/20201030183237-nouns.md | 23 ++ content/wiki/20201030195742-antecedent.md | 15 + ...7-rest_operator_in_object_destructuring.md | 35 ++ .../20201103111509-destructuring_arrays.md | 22 ++ .../20201103111746-destructuring_objects.md | 21 + .../20201103112001-destructuring_iterables.md | 18 + ...1103113124-destructuring_default_values.md | 37 ++ content/wiki/20201104090229-chiffonier.md | 20 + content/wiki/20201104090504-furniture.md | 8 + ...vascript_regexp_numbered_capture_groups.md | 37 ++ ...-javascript_regexp_named_capture_groups.md | 140 +++++++ ...104101723-javascript_regexp_test_method.md | 21 + ...104101924-javascript_regexp_exec_method.md | 22 ++ ...04102212-javascript_regexp_match_method.md | 12 + ...102343-javascript_regexp_replace_method.md | 47 +++ ...4102506-javascript_regexp_search_method.md | 10 + ...ascript_regexp_unicode_property_escapes.md | 85 ++++ content/wiki/20201109120843-chess_terms.md | 7 + content/wiki/20201109120912-fianchetto.md | 13 + content/wiki/20201109121108-percolate.md | 7 + content/wiki/20201109121245-insouciance.md | 7 + content/wiki/20201109121407-epaulet.md | 8 + content/wiki/20201109121522-mirth.md | 7 + content/wiki/20201109121645-imperturbable.md | 7 + content/wiki/20201109121740-wily.md | 7 + content/wiki/20201109121858-chenille.md | 13 + .../wiki/20201109122104-tongue_twisters.md | 7 + content/wiki/20201109122314-precis.md | 7 + content/wiki/20201109122445-anathema.md | 7 + content/wiki/20201109122557-prig.md | 8 + content/wiki/20201109122731-antimacassar.md | 7 + content/wiki/20201109122833-perfunctory.md | 7 + content/wiki/20201109123003-gaberdine.md | 12 + content/wiki/20201109123123-clothing.md | 10 + content/wiki/20201109123326-worsted.md | 9 + content/wiki/20201109123452-anteroom.md | 12 + content/wiki/20201109123541-architecture.md | 7 + content/wiki/20201109123624-sanguine.md | 7 + content/wiki/20201109123736-decanter.md | 12 + content/wiki/20201109123853-glassware.md | 7 + content/wiki/20201109123923-rancor.md | 8 + content/wiki/20201109124059-eidetic.md | 8 + content/wiki/20201109124204-inchmeal.md | 7 + ...9132457-javascript_lookahead_assertions.md | 29 ++ ...132944-javascript_lookbehind_assertions.md | 25 ++ content/wiki/20201109133720-php.md | 75 ++++ content/wiki/20201109133834-php_8_0.md | 72 ++++ content/wiki/20201109133923-php_union_type.md | 40 ++ ...tor_information_in_the_symfony_profiler.md | 8 + content/wiki/20201109140137-symfony_4_0.md | 66 ++++ content/wiki/20201109140300-symfony.md | 44 +++ .../wiki/20201109140430-symfony_validation.md | 19 + content/wiki/20201109140450-symfony_forms.md | 27 ++ ...01109140848-symfony_stopwatch_component.md | 10 + content/wiki/20201109141042-reset_method.md | 7 + .../20201109141116-microseconds_support.md | 9 + ...0201109141325-symfony_console_component.md | 52 +++ content/wiki/20201109141540-lazy_commands.md | 28 ++ .../20201109142218-symfony_annotations.md | 6 + .../wiki/20201109142307-symfony_routing.md | 16 + ...42351-prefix_all_controller_route_names.md | 64 +++ ...109142805-symfony_translation_component.md | 6 + content/wiki/20201109142907-xliff_2_0.md | 50 +++ .../wiki/20201109143227-symfony_profiler.md | 15 + ...ony_user_impersonation_in_debug_toolbar.md | 6 + ...724-groups_support_for_valid_constraint.md | 39 ++ ...bscribing_to_events_in_the_micro_kernel.md | 45 +++ .../20201109150640-expression_constraint.md | 46 +++ ...109150640-expressionlanguage_constraint.md | 46 +++ content/wiki/20201109150950-sessions.md | 8 + content/wiki/20201109151019-lazy_sessions.md | 25 ++ ...9151215-symfony_php7_polyfill_component.md | 7 + .../wiki/20201109151937-debug_autowiring.md | 9 + .../20201109152306-symfony_guard_component.md | 8 + ...7-getcredentials_responsibilities_split.md | 40 ++ content/wiki/20201109152714-debug_form.md | 9 + .../wiki/20201109152907-symfony_commands.md | 14 + .../20201109153159-local_service_binding.md | 61 +++ ...20201110094807-javascript_regexp_s_flag.md | 22 ++ ...20201110095139-javascript_regexp_u_flag.md | 11 + .../20201110100120-php_nullsafe_operator.md | 38 ++ content/wiki/20201110100420-php_attributes.md | 50 +++ ...1308-php_constructor_property_promotion.md | 46 +++ .../20201110102332-php_static_return_type.md | 27 ++ .../20201110102900-php_class_name_literal.md | 21 + ...20201110103409-php_stringable_interface.md | 31 ++ content/wiki/20201110103654-php_weak_maps.md | 32 ++ content/wiki/20201110103654-php_weap_maps.md | 37 ++ content/wiki/20201110152518-symfony_4_1.md | 27 ++ .../wiki/20201110152627-symfony_components.md | 32 ++ ...0152730-symfony_argon2i_password_hasher.md | 36 ++ content/wiki/20201110153351-name_prefix.md | 24 ++ ...201110153611-symfony_workflow_component.md | 11 + ...20201110153948-workflow_dot_format_dump.md | 9 + ...10154017-workflow_planetuml_format_dump.md | 16 + ...110154229-inlined_routing_configuration.md | 40 ++ ...0201110154548-internationalized_routing.md | 80 ++++ .../20201111092510-javascript_strict_mode.md | 42 ++ .../20201111092905-javascript_exceptions.md | 43 +++ ...201111093101-javascript_error_sub_types.md | 11 + .../20201111093227-javascript_rangeerror.md | 10 + ...0201111093310-javascript_referenceerror.md | 10 + .../20201111093338-javascript_syntaxerror.md | 9 + .../20201111093400-javascript_typeerror.md | 11 + .../20201111093418-javascript_urierror.md | 9 + ...111093651-javascript_custom_error_types.md | 31 ++ ...111094033-javascript_exceptions_finally.md | 37 ++ ...11094957-executing_promises_in_parallel.md | 17 + ...uting_promises_in_parallel_promises_all.md | 25 ++ .../20201111095100-catching_promise_errors.md | 17 + ...111095230-javascript_producing_promises.md | 27 ++ .../wiki/20201111095230-producing_promises.md | 23 ++ ...111095316-javascript_consuming_promises.md | 18 + ...01111095454-javascript_promises_finally.md | 39 ++ .../20201111100807-php_throw_expression.md | 37 ++ ...0201111101148-php_non_capturing_catches.md | 36 ++ content/wiki/20201111101706-symfony_4_2.md | 43 +++ ...11103048-symfony_divisibleby_constraint.md | 34 ++ ...111103442-symfony_varexporter_component.md | 75 ++++ ...1111104124-syfmony_console_table_titles.md | 41 ++ ...01111104814-autowiring_by_type_and_name.md | 24 ++ ...0201111105422-symfony_clear_form_errors.md | 25 ++ .../wiki/20201111111255-symfony_autowiring.md | 19 + ...6-fallback_for_internationalized_routes.md | 39 ++ ...1111112055-symfony_serializer_component.md | 14 + content/wiki/20201111112247-serializedname.md | 31 ++ ...341-javascript_string_prototype_methods.md | 17 + ...95428-javascript_string_endswith_method.md | 22 ++ ...2095451-javascript_string_repeat_method.md | 11 + ...95504-javascript_string_includes_method.md | 12 + ...525-javascript_string_startswith_method.md | 18 + ...95657-javascript_string_padstart_method.md | 11 + ...2095711-javascript_string_padend_method.md | 18 + ...201112100548-javascript_string_literals.md | 9 + ...1112100637-javascript_template_literals.md | 23 ++ ...859-javascript_tagged_template_literals.md | 42 ++ ...0201112101218-javascript_string_escapes.md | 8 + ...201112101432-unicode_code_point_escapes.md | 11 + content/wiki/20201112101637-unicode.md | 10 + ...01112101851-javascript_string_iteration.md | 13 + ...7-javascript_string_to_array_conversion.md | 18 + ...2103849-javascript_arithmetic_operators.md | 19 + ...1112103931-javascript_addition_operator.md | 11 + ...2104144-javascript_subtraction_operator.md | 11 + ...4254-javascript_multiplication_operator.md | 11 + ...1112104418-javascript_division_operator.md | 11 + ...2104544-javascript_parenthesis_operator.md | 11 + ...112104654-javascript_remainder_operator.md | 11 + ...01112104819-javascript_string_operators.md | 10 + ...04934-javascript_concatenation_operator.md | 13 + ...201112105050-javascript_unary_operators.md | 10 + ...201112105152-javascript_typeof_operator.md | 16 + ...2105310-javascript_comparison_operators.md | 24 ++ ...1112105647-javascript_logical_operators.md | 21 + ...t_short_circuiting_of_logical_operators.md | 18 + ...javascript_conditional_ternary_operator.md | 12 + ...10203-javascript_exponentation_operator.md | 11 + .../wiki/20201112111910-named_arguments.md | 26 ++ ...13236-trailing_comma_in_parameter_lists.md | 19 + content/wiki/20201112120118-symfony_4_3.md | 96 +++++ ...201112120358-symfony_console_hyperlinks.md | 13 + content/wiki/20201112121020-symfony_il8n.md | 10 + ...416-always_include_route_default_values.md | 38 ++ .../20201112121938-symfony_constraints.md | 52 +++ content/wiki/20201112122929-bic_constraint.md | 20 + ...44-validate_bic_and_iban_codes_together.md | 39 ++ .../20201112123704-cardscheme_constraint.md | 28 ++ ...01112124159-deprecating_service_aliases.md | 34 ++ .../wiki/20201112124304-symfony_services.md | 22 ++ .../20201112124715-symfony_configuration.md | 45 +++ ...4832-automatic_search_engine_protection.md | 20 + .../20201112125413-configurable_session_id.md | 20 + .../20201112125637-symfony_json_constraint.md | 22 ++ content/wiki/20201112125813-symfony_json.md | 9 + ...-symfony_console_iterable_progress_bars.md | 24 ++ content/wiki/20201112130435-iterate_method.md | 33 ++ .../20201112130710-notblank_constraint.md | 25 ++ .../wiki/20201112130816-notblank_allownull.md | 27 ++ ...iguring_services_with_immutable_setters.md | 72 ++++ content/wiki/20201112131845-doctrine.md | 21 + ...ic_validation_based_on_doctrine_mapping.md | 40 ++ .../wiki/20201112132331-unique_constraint.md | 22 ++ .../20201112132747-utf8_routing_option.md | 23 ++ .../20201112132858-symfony_utf_8_support.md | 7 + .../wiki/20201112133603-symfony_passwords.md | 14 + .../20201112133736-sodium_password_encoder.md | 24 ++ .../20201112134545-timezone_constraint.md | 34 ++ .../20201112134545-timezozne_constraint.md | 40 ++ ...2134752-compromised_password_constraint.md | 31 ++ .../wiki/20201112135249-mailer_component.md | 74 ++++ .../20201112135851-symfony_native_encoder.md | 40 ++ .../20201112140448-httpclient_component.md | 41 ++ content/wiki/20201112140650-mime_component.md | 63 +++ .../wiki/20201112140917-number_constraints.md | 43 +++ ...01113090050-javascript_object_operators.md | 11 + .../20201113090337-javascript_in_operator.md | 37 ++ ...1113091110-javascript_object_properties.md | 49 +++ .../20201113091424-javascript_prototypes.md | 38 ++ .../wiki/20201113092454-javascript_symbols.md | 92 +++++ .../20201113092902-javascript_primitives.md | 7 + ...204-javascript_object_prototype_methods.md | 54 +++ ...201113093613-javascript_object_keywords.md | 7 + .../20201113093910-javascript_new_keyword.md | 28 ++ ...13094246-javascript_instanceof_operator.md | 41 ++ ...201113094652-javascript_delete_operator.md | 22 ++ content/wiki/20201113095226-object_keys.md | 16 + content/wiki/20201113095244-object_assign.md | 18 + content/wiki/20201113095300-object_is.md | 17 + content/wiki/20201113102048-object_entries.md | 30 ++ content/wiki/20201113102106-object_values.md | 15 + ...102125-object_getownpropertydescriptors.md | 34 ++ ...201113103917-javascript_array_functions.md | 8 + .../20201113104217-array_prototype_fill.md | 12 + ...201113104240-array_prototype_copywithin.md | 24 ++ ...0201113104332-array_prototype_findindex.md | 11 + .../20201113104352-array_prototype_find.md | 11 + .../20201113104423-array_prototype_entries.md | 11 + .../20201113104438-array_prototype_values.md | 11 + .../20201113104454-array_prototype_keys.md | 11 + ...13104552-array_search_prototype_methods.md | 8 + ...04619-array_iteration_prototype_methods.md | 9 + ...20201113105707-array_prototype_includes.md | 16 + content/wiki/20201113105832-array_from.md | 23 ++ content/wiki/20201113105847-array_of.md | 15 + content/wiki/20201113111815-es2019.md | 41 ++ .../20201113112029-array_prototype_flat.md | 23 ++ .../20201113112058-array_prototype_flatmap.md | 32 ++ .../20201113113141-array_prototype_map.md | 19 + .../20201113115201-php_string_functions.md | 11 + content/wiki/20201113115231-str_contains.md | 19 + .../wiki/20201113115424-str_starts_with.md | 20 + content/wiki/20201113115452-str_ends_with.md | 21 + .../wiki/20201113115907-php_type_functions.md | 7 + content/wiki/20201113115939-get_debug_type.md | 29 ++ .../20201113120212-php_resource_functions.md | 7 + .../wiki/20201113120246-get_resource_id.md | 19 + .../wiki/20201113121741-php_expressions.md | 8 + .../wiki/20201113121813-match_expression.md | 115 ++++++ .../wiki/20201113122000-switch_expression.md | 31 ++ content/wiki/20201113122505-php_types.md | 8 + content/wiki/20201113122801-php_functions.md | 9 + content/wiki/20201113122959-php_mixed_type.md | 14 + content/wiki/20201113123224-php_objects.md | 7 + content/wiki/20201113123254-datetime.md | 10 + .../20201113123327-createfrominterface.md | 18 + .../20201113123648-createfromimmutable.md | 17 + content/wiki/20201113172025-symfony_5_0.md | 65 ++++ .../wiki/20201113172517-type_constraint.md | 46 +++ ...ype_constraint_can_be_an_array_of_types.md | 24 ++ ...3173159-signing_and_encrypting_messages.md | 42 ++ .../20201113174016-notification_emails.md | 29 ++ content/wiki/20201113174255-encryption.md | 10 + ...01113174444-ecrypted_secrets_management.md | 54 +++ content/wiki/20201113175016-events.md | 19 + content/wiki/20201113175145-listeners.md | 14 + content/wiki/20201113175249-subscribers.md | 10 + .../wiki/20201113175527-event_listeners.md | 20 + .../20201113180227-simpler_event_listeners.md | 29 ++ ...0201113180551-doctrine_entity_listeners.md | 12 + ...722-invokable_doctrine_entity_listeners.md | 37 ++ .../wiki/20201113180928-horizontal_tables.md | 27 ++ ...201113181152-symfony_style_for_commands.md | 9 + .../wiki/20201113181235-horizontaltable.md | 22 ++ .../wiki/20201113181356-definition_lists.md | 33 ++ .../20201113181759-password_migrations.md | 43 +++ ...20201113182438-httpfoundation_component.md | 9 + .../20201113182523-ip_address_anonymizer.md | 23 ++ content/wiki/20201113182753-week_form_type.md | 34 ++ content/wiki/20201113183038-lazy_firewalls.md | 18 + .../wiki/20201113183209-symfony_firewalls.md | 7 + .../wiki/20201113183442-string_component.md | 84 ++++ ...20201113183442-symfony_string_component.md | 100 +++++ content/wiki/20201114101358-quotes.md | 13 + ...rs_to_scrape_the_bodies_off_the_streets.md | 10 + .../wiki/20201114101721-political_science.md | 8 + .../20201114101926-american_presidents.md | 7 + .../20201114102043-dwight_d_eisenhower.md | 13 + content/wiki/20201114102140-nuclear_war.md | 11 + .../20201115141421-conventional_changelog.md | 18 + .../wiki/20201115141620-commit_guidelines.md | 60 +++ .../wiki/20201116095124-object_fromentries.md | 22 ++ content/wiki/20201116100205-trimstart.md | 16 + content/wiki/20201116100239-trimend.md | 16 + content/wiki/20201116100345-trim.md | 19 + ...926-characters_that_count_as_whitespace.md | 28 ++ ...443-javascript_symbol_prototype_methods.md | 7 + ...1116101509-symbol_prototype_description.md | 21 + content/wiki/20201116105919-symfony_5_1.md | 120 ++++++ .../wiki/20201116121447-symfony_security.md | 9 + ...01116121519-symfony_security_attributes.md | 19 + ...01116121636-is_authenticated_remembered.md | 6 + .../20201116121711-is_authenticated_fully.md | 6 + content/wiki/20201116121759-is_remembered.md | 40 ++ .../20201116122125-role_previous_admin.md | 22 ++ .../wiki/20201116122525-is_impersonator.md | 25 ++ ...201116123857-route_annotations_priority.md | 35 ++ .../20201116124210-compound_constraint.md | 55 +++ .../20201116124823-sequentially_constraint.md | 25 ++ ...01116125148-single_command_applications.md | 47 +++ .../20201116125716-stringable_interface.md | 9 + content/wiki/20201116130210-truncate.md | 19 + content/wiki/20201116130327-keep_last_word.md | 18 + content/wiki/20201116130503-containsany.md | 19 + content/wiki/20201116130738-reverse.md | 19 + content/wiki/20201116131057-stateless.md | 32 ++ ...131633-use_env_vars_in_route_conditions.md | 18 + .../20201116131815-symfony_uuid_component.md | 56 +++ .../20201116132411-hostname_constraint.md | 26 ++ .../wiki/20201116132826-service_decoration.md | 28 ++ .../wiki/20201116133113-stack_decorators.md | 21 + ...201116133423-simpler_service_decoration.md | 23 ++ ...201116133627-different_hosts_per_locale.md | 17 + content/wiki/20201116133907-logoutevent.md | 22 ++ .../20201116134142-console_cursor_control.md | 59 +++ .../20201116134435-atleastoneof_constraint.md | 60 +++ ...e_public_services_into_private_services.md | 26 ++ ...523-expressionlanguagesyntax_constraint.md | 34 ++ ...1116135741-expressionlanguage_component.md | 13 + .../wiki/20201116135915-expression_linter.md | 34 ++ content/wiki/20201116140434-ignore.md | 51 +++ ...01116140847-symfony_contracts_component.md | 9 + .../20201116140934-trigger_depcreation.md | 23 ++ content/wiki/20201116141232-lint_yaml.md | 15 + content/wiki/20201116141414-linters.md | 13 + .../wiki/20201116141657-command_success.md | 38 ++ content/wiki/20201116141817-command_error.md | 38 ++ .../20201116142023-filesystem_component.md | 7 + content/wiki/20201116142105-tempnam.md | 21 + content/wiki/20201116142317-fromrandom.md | 17 + ...0201116142601-optionsresolver_component.md | 13 + content/wiki/20201116142709-define.md | 20 + .../wiki/20201116142916-symfony_resolver.md | 6 + content/wiki/20201116143004-info_setinfo.md | 24 ++ .../20201116143401-symfony_security_voters.md | 12 + content/wiki/20201116143526-affirmative.md | 9 + content/wiki/20201116143625-consensus.md | 9 + content/wiki/20201116143708-unanimous.md | 9 + content/wiki/20201116143740-priority.md | 21 + ...20201116154444-javascript_catch_binding.md | 15 + ...54824-javascript_optional_catch_binding.md | 26 ++ .../20201116155459-array_prototype_sort.md | 26 ++ ...6155810-sort_is_guaranteed_to_be_stable.md | 22 ++ content/wiki/20201116162058-es2020.md | 37 ++ ...01116162237-nullish_coalescing_operator.md | 20 + ...201116162628-optional_chaining_operator.md | 27 ++ .../wiki/20201116163327-promise_allsettled.md | 16 + .../wiki/20201116163755-fractional_numbers.md | 11 + .../20201116163844-scientific_notation.md | 11 + content/wiki/20201116163925-infinity.md | 18 + content/wiki/20201116164007-nan.md | 16 + .../wiki/20201116164748-binary_notation.md | 11 + content/wiki/20201116164828-octal_notation.md | 11 + .../20201116165324-matchall_expression.md | 18 + .../wiki/20201116165819-javascript_bigint.md | 29 ++ content/wiki/20201116170151-dynamic_import.md | 15 + ...20201116170347-module_namespace_exports.md | 16 + content/wiki/20201116170538-globalthis.md | 24 ++ content/wiki/20201116182958-indolent.md | 7 + content/wiki/20201117095953-symfony_5_2.md | 84 ++++ ...17100112-pseudo_localization_translator.md | 53 +++ .../20201117100855-true_console_colours.md | 35 ++ ...1117101232-symfony_doctrine_integration.md | 22 ++ .../wiki/20201117101452-uuid_ulid_types.md | 77 ++++ .../wiki/20201117102242-syfony_controller.md | 15 + ...-symfony_controller_argument_attributes.md | 15 + content/wiki/20201117102746-currentuser.md | 29 ++ content/wiki/20201117103021-symfony_user.md | 12 + ...llback_functions_to_get_set_form_fields.md | 44 +++ .../wiki/20201117103957-uuid_normalizer.md | 38 ++ .../wiki/20201117104332-ulid_constraint.md | 29 ++ ...0201117104659-dkim_email_authentication.md | 32 ++ content/wiki/20201117105045-rout.md | 42 ++ ...201117105314-symfony_routing_attributes.md | 9 + ...01117105617-symfony_routing_annotations.md | 36 ++ ...1117110902-symfony_doctrine_annotations.md | 9 + .../wiki/20201117111410-symfony_attributes.md | 31 ++ content/wiki/20201117111757-required.md | 27 ++ content/wiki/20201117112017-required.md | 61 +++ ...112727-define_constraints_as_attributes.md | 67 ++++ ...117113404-symfony_ratelimiter_component.md | 60 +++ .../wiki/20201117114036-login_throttling.md | 38 ++ ...17114443-front_controller_configuration.md | 40 ++ .../wiki/20201117114930-console_signals.md | 46 +++ .../20201117115146-consoleevents_signal.md | 36 ++ content/wiki/20201119165257-rust_1_48.md | 59 +++ content/wiki/20201119165454-rustdoc.md | 38 ++ content/wiki/20201119165530-rust_tooling.md | 25 ++ ...20201119170237-linking_to_items_by_name.md | 64 +++ content/wiki/20201119170710-search_aliases.md | 22 ++ content/wiki/20201119171245-tryinto.md | 31 ++ content/wiki/20201120094652-cargo_toml.md | 7 + content/wiki/20201120095606-slice.md | 10 + .../20201120095639-rust_primitive_types.md | 7 + content/wiki/20201120095739-as_ptr_range.md | 49 +++ .../wiki/20201120101047-as_mut_ptr_range.md | 33 ++ content/wiki/20201120102004-rust_pointers.md | 20 + content/wiki/20201120103547-rust_traits.md | 7 + content/wiki/20201120103613-trait_std.md | 7 + content/wiki/20201120103652-convert.md | 7 + ..._vector_into_an_array_of_a_given_length.md | 28 ++ content/wiki/20201120105306-rust_structs.md | 7 + content/wiki/20201120105504-struct_std.md | 7 + content/wiki/20201120105522-collections.md | 7 + content/wiki/20201120105602-vecdeque.md | 9 + content/wiki/20201120110719-rust_functions.md | 11 + content/wiki/20201120110752-function_std.md | 7 + content/wiki/20201120110819-future.md | 8 + content/wiki/20201120110842-pending.md | 37 ++ content/wiki/20201120111157-ready.md | 39 ++ content/wiki/20201121083531-movie_ideas.md | 8 + content/wiki/20201123094735-typescript_4_1.md | 49 +++ ...23100551-typescript_string_literal_type.md | 93 +++++ ...3100939-typescript_boolean_literal_type.md | 15 + ...23101123-typescript_number_literal_type.md | 15 + ...typescript_template_literal_string_type.md | 137 +++++++ content/wiki/20201123103250-uppercase.md | 20 + content/wiki/20201123103315-lowercase.md | 20 + content/wiki/20201123103333-capitalize.md | 20 + content/wiki/20201123103400-uncapitalize.md | 20 + .../20201124085335-typescript_mapped_type.md | 35 ++ .../20201124090450-typescript_in_operator.md | 30 ++ ...124091025-typescript_literal_type_guard.md | 48 +++ ...01124091530-typescript_strictnullchecks.md | 19 + ...740-typescript_user_defined_type_guards.md | 48 +++ .../20201124095453-typescript_as_clause.md | 56 +++ ...-typescript_recursive_conditional_types.md | 77 ++++ .../wiki/20201126095254-programming_terms.md | 15 + content/wiki/20201126095525-idempotent.md | 54 +++ content/wiki/20201126100331-ephemeral.md | 40 ++ content/wiki/20201126100942-anonymous.md | 23 ++ content/wiki/20201126101327-predicate.md | 45 +++ content/wiki/20201126101955-memoization.md | 33 ++ content/wiki/20201126102708-abstraction.md | 30 ++ content/wiki/20201126103142-serialization.md | 33 ++ .../20201126104931-nouncheckedindexaccess.md | 97 +++++ content/wiki/20201127100908-checkjs.md | 9 + content/wiki/20201127100938-allowjs.md | 13 + .../wiki/20201127101043-typescript_flags.md | 12 + content/wiki/20201127101336-checkjs.md | 19 + content/wiki/20201130084544-react.md | 7 + .../20201130084608-react_factory_functions.md | 10 + ...201130084644-jsx_react_factory_function.md | 6 + ...01130084716-jsxs_react_factory_function.md | 6 + .../20201130085124-typescript_jsx_flag.md | 16 + content/wiki/20201130085253-react_jsx.md | 32 ++ content/wiki/20201130085317-react_jsxdev.md | 28 ++ content/wiki/20210405114813-technical_debt.md | 25 ++ content/wiki/20210405114931-code_debt.md | 10 + content/wiki/20210405115333-design_debt.md | 25 ++ content/wiki/20210405115411-test_debt.md | 7 + .../wiki/20210405115459-documentation_debt.md | 11 + .../wiki/20210405120239-software_design.md | 8 + ...uality_attributes_and_their_definitions.md | 16 + ...d_abstraction_on_key_quality_attributes.md | 55 +++ content/wiki/20210405123214-viscosity.md | 10 + .../wiki/20211015195242-development_tools.md | 10 + content/wiki/20220212123754-gitlab.md | 46 +++ content/wiki/20220219131642-ipv6.md | 37 ++ ...634-pournelle_s_iron_law_of_bureaucracy.md | 28 ++ content/wiki/20220507131835-ci_cd.md | 9 + content/wiki/20220507132217-dns.md | 10 + content/wiki/20220507132251-stubby.md | 20 + content/wiki/20220507132657-dnscrypt.md | 23 ++ content/wiki/20220917160601-tawdry.md | 9 + content/wiki/index.md | 69 ++++ 633 files changed, 23051 insertions(+) create mode 100644 content/wiki/20200613170532-variable_types_in_javascript.md create mode 100644 content/wiki/20200613170705-operators_in_javascript.md create mode 100644 content/wiki/20200613170756-javascript_type_conversion.md create mode 100644 content/wiki/20200613170756-type_conversion_in_javascript.md create mode 100644 content/wiki/20200613170905-javascript.md create mode 100644 content/wiki/20200613170934-javascript_books.md create mode 100644 content/wiki/20200613171743-javascript_types.md create mode 100644 content/wiki/20200613172137-binding_variables_in_javascript.md create mode 100644 content/wiki/20200613172534-control_flows_in_javascript.md create mode 100644 content/wiki/20200613172534-javascript_control_flows.md create mode 100644 content/wiki/20200702203250-bindings_and_scopes.md create mode 100644 content/wiki/20200702204226-optional_arguments.md create mode 100644 content/wiki/20200702204351-closure.md create mode 100644 content/wiki/20200702204437-recursion.md create mode 100644 content/wiki/20200704151304-history.md create mode 100644 content/wiki/20200704151508-economic_state_of_ussr_1942_1943.md create mode 100644 content/wiki/20200704151715-economics.md create mode 100644 content/wiki/20200704151950-ledger.md create mode 100644 content/wiki/20200704152249-vocabulary.md create mode 100644 content/wiki/20200704152442-rust.md create mode 100644 content/wiki/20200706161134-stages_of_islamic_history.md create mode 100644 content/wiki/20200706164411-stages_of_christian_history.md create mode 100644 content/wiki/20200706165803-the_chaldeans.md create mode 100644 content/wiki/20200826142641-golang.md create mode 100644 content/wiki/20200826142755-packages.md create mode 100644 content/wiki/20200826151337-functions.md create mode 100644 content/wiki/20200826151514-variables.md create mode 100644 content/wiki/20200826151846-flow_control_statements.md create mode 100644 content/wiki/20200826191127-tests.md create mode 100644 content/wiki/20200826191508-tooling.md create mode 100644 content/wiki/20200826201029-arrays.md create mode 100644 content/wiki/20200826201605-objects.md create mode 100644 content/wiki/20200826201737-mutability.md create mode 100644 content/wiki/20200826201856-object_operators.md create mode 100644 content/wiki/20200826201959-object_functions.md create mode 100644 content/wiki/20200827142818-higher_order_functions.md create mode 100644 content/wiki/20200827170931-functions_macros.md create mode 100644 content/wiki/20200827171036-tooling.md create mode 100644 content/wiki/20200827171318-rust_books.md create mode 100644 content/wiki/20200827171554-variables_in_rust.md create mode 100644 content/wiki/20200827190035-rust_comments.md create mode 100644 content/wiki/20200827190443-rust_control_flow.md create mode 100644 content/wiki/20200828170945-ownership.md create mode 100644 content/wiki/20200828180957-pointers.md create mode 100644 content/wiki/20200828181259-structs.md create mode 100644 content/wiki/20200828182327-arrays.md create mode 100644 content/wiki/20200828182546-slices.md create mode 100644 content/wiki/20200828192034-maps.md create mode 100644 content/wiki/20200831155304-methods.md create mode 100644 content/wiki/20200831171822-interfaces.md create mode 100644 content/wiki/20200831193417-structs.md create mode 100644 content/wiki/20200901105237-error_handling.md create mode 100644 content/wiki/20200901141141-goroutines.md create mode 100644 content/wiki/20200902150714-enums.md create mode 100644 content/wiki/20200902162305-regular_expressions.md create mode 100644 content/wiki/20200909202454-errors.md create mode 100644 content/wiki/20200911150451-callbacks.md create mode 100644 content/wiki/20200911154351-promises.md create mode 100644 content/wiki/20200911155947-generators.md create mode 100644 content/wiki/20200915140449-vectors.md create mode 100644 content/wiki/20200915151358-strings.md create mode 100644 content/wiki/20200915153033-hash_maps.md create mode 100644 content/wiki/20200916162727-unrecoverable_errors.md create mode 100644 content/wiki/20200916163737-recoverable_errors.md create mode 100644 content/wiki/20200916172802-commonjs.md create mode 100644 content/wiki/20200916172914-ecmascript.md create mode 100644 content/wiki/20200917155644-reflection.md create mode 100644 content/wiki/20200917161757-generics.md create mode 100644 content/wiki/20200917163203-traits.md create mode 100644 content/wiki/20200918173820-mutex.md create mode 100644 content/wiki/20200918174548-waitgroup.md create mode 100644 content/wiki/20200918180634-rustc.md create mode 100644 content/wiki/20200918180750-cargo.md create mode 100644 content/wiki/20200918183524-tests.md create mode 100644 content/wiki/20200921154246-context.md create mode 100644 content/wiki/20200922160850-destructuring.md create mode 100644 content/wiki/20200922162003-parameter_default_values.md create mode 100644 content/wiki/20200922162127-named_parameters.md create mode 100644 content/wiki/20200922162500-rest_parameters.md create mode 100644 content/wiki/20200922164416-numbers.md create mode 100644 content/wiki/20200922164551-strings.md create mode 100644 content/wiki/20200922164727-booleans.md create mode 100644 content/wiki/20200922164830-empty_values.md create mode 100644 content/wiki/20200923144022-closures.md create mode 100644 content/wiki/20200923150006-iterators.md create mode 100644 content/wiki/20200923153425-number.md create mode 100644 content/wiki/20200923153614-math.md create mode 100644 content/wiki/20200928193245-embedding.md create mode 100644 content/wiki/20200929135609-box_t.md create mode 100644 content/wiki/20200929141711-deref_trait.md create mode 100644 content/wiki/20200929142932-drop_trait.md create mode 100644 content/wiki/20200929145534-rc_t.md create mode 100644 content/wiki/20200929152628-refcell_t.md create mode 100644 content/wiki/20200929161126-basic_annotations.md create mode 100644 content/wiki/20200929161126-typescript.md create mode 100644 content/wiki/20200929161544-primitive_types.md create mode 100644 content/wiki/20200929162129-arrays.md create mode 100644 content/wiki/20200929162220-interfaces.md create mode 100644 content/wiki/20200929162417-inline_type_annotation.md create mode 100644 content/wiki/20200929163051-typescript_generics.md create mode 100644 content/wiki/20200929163219-typescript_union_type.md create mode 100644 content/wiki/20200929163316-typescript_intersection_type.md create mode 100644 content/wiki/20200929163624-typescript_tuple_type.md create mode 100644 content/wiki/20200929163825-typescript_type_alias.md create mode 100644 content/wiki/20200930105954-ambient_declarations.md create mode 100644 content/wiki/20200930110721-typescript_enums.md create mode 100644 content/wiki/20200930121904-rust_threads.md create mode 100644 content/wiki/20200930123003-message_passing.md create mode 100644 content/wiki/20200930123749-rust_shared_state_concurrency.md create mode 100644 content/wiki/20201001105545-lib_d_ts.md create mode 100644 content/wiki/20201001110806-typescript_functions.md create mode 100644 content/wiki/20201001112126-typescript_callable.md create mode 100644 content/wiki/20201002101745-typescript_type_assertion.md create mode 100644 content/wiki/20201002102455-typescript_type_guard.md create mode 100644 content/wiki/20201002103357-typescript_literal_types.md create mode 100644 content/wiki/20201005171253-readonly.md create mode 100644 content/wiki/20201006102934-pattern_syntax.md create mode 100644 content/wiki/20201006111125-javascript_function_declerations.md create mode 100644 content/wiki/20201006111244-declaration_notation.md create mode 100644 content/wiki/20201006111349-arrow_functions.md create mode 100644 content/wiki/20201007093418-javascript_object_getters_setters.md create mode 100644 content/wiki/20201007095614-typescript_never_type.md create mode 100644 content/wiki/20201007101133-typescript_discriminated_union.md create mode 100644 content/wiki/20201008090316-class_notation.md create mode 100644 content/wiki/20201008090449-method_definition.md create mode 100644 content/wiki/20201008090613-inheritance.md create mode 100644 content/wiki/20201008092225-index_signatures.md create mode 100644 content/wiki/20201009090331-javascript_array_methods.md create mode 100644 content/wiki/20201009090331-javascript_array_prototype_methods.md create mode 100644 content/wiki/20201009104050-typescript_4_0.md create mode 100644 content/wiki/20201009104411-typescript_classes.md create mode 100644 content/wiki/20201012093745-javascript_maps.md create mode 100644 content/wiki/20201012094248-javascript_sets.md create mode 100644 content/wiki/20201012094749-javascript_weakmaps.md create mode 100644 content/wiki/20201014092625-javascript_iterables.md create mode 100644 content/wiki/20201014092846-javascript_iterator.md create mode 100644 content/wiki/20201014094144-spread.md create mode 100644 content/wiki/20201021141613-vue_js.md create mode 100644 content/wiki/20201022094207-javascript_proxies.md create mode 100644 content/wiki/20201022095438-javascript_metaprogramming.md create mode 100644 content/wiki/20201023130243-es2016.md create mode 100644 content/wiki/20201026103714-javascript_async_functions.md create mode 100644 content/wiki/20201026104538-es2017.md create mode 100644 content/wiki/20201029194838-carthaginian_peace.md create mode 100644 content/wiki/20201029195142-detritus.md create mode 100644 content/wiki/20201029195302-useful_idiot.md create mode 100644 content/wiki/20201029195404-intercommunicating_zones.md create mode 100644 content/wiki/20201029195742-historical_terms.md create mode 100644 content/wiki/20201029195945-geographic_terms.md create mode 100644 content/wiki/20201029195945-geographical_terms.md create mode 100644 content/wiki/20201029200040-political_science_terms.md create mode 100644 content/wiki/20201029200235-podophilia.md create mode 100644 content/wiki/20201029200327-sexual_terms.md create mode 100644 content/wiki/20201029201415-bluestocking.md create mode 100644 content/wiki/20201029204128-gregarious.md create mode 100644 content/wiki/20201029204304-adjectives.md create mode 100644 content/wiki/20201030092200-javascript_async_iterator.md create mode 100644 content/wiki/20201030093304-javascript_for_of.md create mode 100644 content/wiki/20201030093404-es6.md create mode 100644 content/wiki/20201030093832-javascript_if_statement.md create mode 100644 content/wiki/20201030094040-javascript_for_statement.md create mode 100644 content/wiki/20201030094138-javascript_switch_statement.md create mode 100644 content/wiki/20201030094343-javascript_breaking_out_of_a_loop.md create mode 100644 content/wiki/20201030094749-javascript_comments.md create mode 100644 content/wiki/20201030095105-es2018.md create mode 100644 content/wiki/20201030095741-javascript_for_await_of.md create mode 100644 content/wiki/20201030182939-verbs.md create mode 100644 content/wiki/20201030183019-geld.md create mode 100644 content/wiki/20201030183237-nouns.md create mode 100644 content/wiki/20201030195742-antecedent.md create mode 100644 content/wiki/20201103111357-rest_operator_in_object_destructuring.md create mode 100644 content/wiki/20201103111509-destructuring_arrays.md create mode 100644 content/wiki/20201103111746-destructuring_objects.md create mode 100644 content/wiki/20201103112001-destructuring_iterables.md create mode 100644 content/wiki/20201103113124-destructuring_default_values.md create mode 100644 content/wiki/20201104090229-chiffonier.md create mode 100644 content/wiki/20201104090504-furniture.md create mode 100644 content/wiki/20201104095851-javascript_regexp_numbered_capture_groups.md create mode 100644 content/wiki/20201104100431-javascript_regexp_named_capture_groups.md create mode 100644 content/wiki/20201104101723-javascript_regexp_test_method.md create mode 100644 content/wiki/20201104101924-javascript_regexp_exec_method.md create mode 100644 content/wiki/20201104102212-javascript_regexp_match_method.md create mode 100644 content/wiki/20201104102343-javascript_regexp_replace_method.md create mode 100644 content/wiki/20201104102506-javascript_regexp_search_method.md create mode 100644 content/wiki/20201106090634-javascript_regexp_unicode_property_escapes.md create mode 100644 content/wiki/20201109120843-chess_terms.md create mode 100644 content/wiki/20201109120912-fianchetto.md create mode 100644 content/wiki/20201109121108-percolate.md create mode 100644 content/wiki/20201109121245-insouciance.md create mode 100644 content/wiki/20201109121407-epaulet.md create mode 100644 content/wiki/20201109121522-mirth.md create mode 100644 content/wiki/20201109121645-imperturbable.md create mode 100644 content/wiki/20201109121740-wily.md create mode 100644 content/wiki/20201109121858-chenille.md create mode 100644 content/wiki/20201109122104-tongue_twisters.md create mode 100644 content/wiki/20201109122314-precis.md create mode 100644 content/wiki/20201109122445-anathema.md create mode 100644 content/wiki/20201109122557-prig.md create mode 100644 content/wiki/20201109122731-antimacassar.md create mode 100644 content/wiki/20201109122833-perfunctory.md create mode 100644 content/wiki/20201109123003-gaberdine.md create mode 100644 content/wiki/20201109123123-clothing.md create mode 100644 content/wiki/20201109123326-worsted.md create mode 100644 content/wiki/20201109123452-anteroom.md create mode 100644 content/wiki/20201109123541-architecture.md create mode 100644 content/wiki/20201109123624-sanguine.md create mode 100644 content/wiki/20201109123736-decanter.md create mode 100644 content/wiki/20201109123853-glassware.md create mode 100644 content/wiki/20201109123923-rancor.md create mode 100644 content/wiki/20201109124059-eidetic.md create mode 100644 content/wiki/20201109124204-inchmeal.md create mode 100644 content/wiki/20201109132457-javascript_lookahead_assertions.md create mode 100644 content/wiki/20201109132944-javascript_lookbehind_assertions.md create mode 100644 content/wiki/20201109133720-php.md create mode 100644 content/wiki/20201109133834-php_8_0.md create mode 100644 content/wiki/20201109133923-php_union_type.md create mode 100644 content/wiki/20201109140046-validator_information_in_the_symfony_profiler.md create mode 100644 content/wiki/20201109140137-symfony_4_0.md create mode 100644 content/wiki/20201109140300-symfony.md create mode 100644 content/wiki/20201109140430-symfony_validation.md create mode 100644 content/wiki/20201109140450-symfony_forms.md create mode 100644 content/wiki/20201109140848-symfony_stopwatch_component.md create mode 100644 content/wiki/20201109141042-reset_method.md create mode 100644 content/wiki/20201109141116-microseconds_support.md create mode 100644 content/wiki/20201109141325-symfony_console_component.md create mode 100644 content/wiki/20201109141540-lazy_commands.md create mode 100644 content/wiki/20201109142218-symfony_annotations.md create mode 100644 content/wiki/20201109142307-symfony_routing.md create mode 100644 content/wiki/20201109142351-prefix_all_controller_route_names.md create mode 100644 content/wiki/20201109142805-symfony_translation_component.md create mode 100644 content/wiki/20201109142907-xliff_2_0.md create mode 100644 content/wiki/20201109143227-symfony_profiler.md create mode 100644 content/wiki/20201109143336-symfony_user_impersonation_in_debug_toolbar.md create mode 100644 content/wiki/20201109145724-groups_support_for_valid_constraint.md create mode 100644 content/wiki/20201109150109-subscribing_to_events_in_the_micro_kernel.md create mode 100644 content/wiki/20201109150640-expression_constraint.md create mode 100644 content/wiki/20201109150640-expressionlanguage_constraint.md create mode 100644 content/wiki/20201109150950-sessions.md create mode 100644 content/wiki/20201109151019-lazy_sessions.md create mode 100644 content/wiki/20201109151215-symfony_php7_polyfill_component.md create mode 100644 content/wiki/20201109151937-debug_autowiring.md create mode 100644 content/wiki/20201109152306-symfony_guard_component.md create mode 100644 content/wiki/20201109152527-getcredentials_responsibilities_split.md create mode 100644 content/wiki/20201109152714-debug_form.md create mode 100644 content/wiki/20201109152907-symfony_commands.md create mode 100644 content/wiki/20201109153159-local_service_binding.md create mode 100644 content/wiki/20201110094807-javascript_regexp_s_flag.md create mode 100644 content/wiki/20201110095139-javascript_regexp_u_flag.md create mode 100644 content/wiki/20201110100120-php_nullsafe_operator.md create mode 100644 content/wiki/20201110100420-php_attributes.md create mode 100644 content/wiki/20201110101308-php_constructor_property_promotion.md create mode 100644 content/wiki/20201110102332-php_static_return_type.md create mode 100644 content/wiki/20201110102900-php_class_name_literal.md create mode 100644 content/wiki/20201110103409-php_stringable_interface.md create mode 100644 content/wiki/20201110103654-php_weak_maps.md create mode 100644 content/wiki/20201110103654-php_weap_maps.md create mode 100644 content/wiki/20201110152518-symfony_4_1.md create mode 100644 content/wiki/20201110152627-symfony_components.md create mode 100644 content/wiki/20201110152730-symfony_argon2i_password_hasher.md create mode 100644 content/wiki/20201110153351-name_prefix.md create mode 100644 content/wiki/20201110153611-symfony_workflow_component.md create mode 100644 content/wiki/20201110153948-workflow_dot_format_dump.md create mode 100644 content/wiki/20201110154017-workflow_planetuml_format_dump.md create mode 100644 content/wiki/20201110154229-inlined_routing_configuration.md create mode 100644 content/wiki/20201110154548-internationalized_routing.md create mode 100644 content/wiki/20201111092510-javascript_strict_mode.md create mode 100644 content/wiki/20201111092905-javascript_exceptions.md create mode 100644 content/wiki/20201111093101-javascript_error_sub_types.md create mode 100644 content/wiki/20201111093227-javascript_rangeerror.md create mode 100644 content/wiki/20201111093310-javascript_referenceerror.md create mode 100644 content/wiki/20201111093338-javascript_syntaxerror.md create mode 100644 content/wiki/20201111093400-javascript_typeerror.md create mode 100644 content/wiki/20201111093418-javascript_urierror.md create mode 100644 content/wiki/20201111093651-javascript_custom_error_types.md create mode 100644 content/wiki/20201111094033-javascript_exceptions_finally.md create mode 100644 content/wiki/20201111094957-executing_promises_in_parallel.md create mode 100644 content/wiki/20201111094957-executing_promises_in_parallel_promises_all.md create mode 100644 content/wiki/20201111095100-catching_promise_errors.md create mode 100644 content/wiki/20201111095230-javascript_producing_promises.md create mode 100644 content/wiki/20201111095230-producing_promises.md create mode 100644 content/wiki/20201111095316-javascript_consuming_promises.md create mode 100644 content/wiki/20201111095454-javascript_promises_finally.md create mode 100644 content/wiki/20201111100807-php_throw_expression.md create mode 100644 content/wiki/20201111101148-php_non_capturing_catches.md create mode 100644 content/wiki/20201111101706-symfony_4_2.md create mode 100644 content/wiki/20201111103048-symfony_divisibleby_constraint.md create mode 100644 content/wiki/20201111103442-symfony_varexporter_component.md create mode 100644 content/wiki/20201111104124-syfmony_console_table_titles.md create mode 100644 content/wiki/20201111104814-autowiring_by_type_and_name.md create mode 100644 content/wiki/20201111105422-symfony_clear_form_errors.md create mode 100644 content/wiki/20201111111255-symfony_autowiring.md create mode 100644 content/wiki/20201111111636-fallback_for_internationalized_routes.md create mode 100644 content/wiki/20201111112055-symfony_serializer_component.md create mode 100644 content/wiki/20201111112247-serializedname.md create mode 100644 content/wiki/20201112095341-javascript_string_prototype_methods.md create mode 100644 content/wiki/20201112095428-javascript_string_endswith_method.md create mode 100644 content/wiki/20201112095451-javascript_string_repeat_method.md create mode 100644 content/wiki/20201112095504-javascript_string_includes_method.md create mode 100644 content/wiki/20201112095525-javascript_string_startswith_method.md create mode 100644 content/wiki/20201112095657-javascript_string_padstart_method.md create mode 100644 content/wiki/20201112095711-javascript_string_padend_method.md create mode 100644 content/wiki/20201112100548-javascript_string_literals.md create mode 100644 content/wiki/20201112100637-javascript_template_literals.md create mode 100644 content/wiki/20201112100859-javascript_tagged_template_literals.md create mode 100644 content/wiki/20201112101218-javascript_string_escapes.md create mode 100644 content/wiki/20201112101432-unicode_code_point_escapes.md create mode 100644 content/wiki/20201112101637-unicode.md create mode 100644 content/wiki/20201112101851-javascript_string_iteration.md create mode 100644 content/wiki/20201112102537-javascript_string_to_array_conversion.md create mode 100644 content/wiki/20201112103849-javascript_arithmetic_operators.md create mode 100644 content/wiki/20201112103931-javascript_addition_operator.md create mode 100644 content/wiki/20201112104144-javascript_subtraction_operator.md create mode 100644 content/wiki/20201112104254-javascript_multiplication_operator.md create mode 100644 content/wiki/20201112104418-javascript_division_operator.md create mode 100644 content/wiki/20201112104544-javascript_parenthesis_operator.md create mode 100644 content/wiki/20201112104654-javascript_remainder_operator.md create mode 100644 content/wiki/20201112104819-javascript_string_operators.md create mode 100644 content/wiki/20201112104934-javascript_concatenation_operator.md create mode 100644 content/wiki/20201112105050-javascript_unary_operators.md create mode 100644 content/wiki/20201112105152-javascript_typeof_operator.md create mode 100644 content/wiki/20201112105310-javascript_comparison_operators.md create mode 100644 content/wiki/20201112105647-javascript_logical_operators.md create mode 100644 content/wiki/20201112105833-javascript_short_circuiting_of_logical_operators.md create mode 100644 content/wiki/20201112110025-javascript_conditional_ternary_operator.md create mode 100644 content/wiki/20201112110203-javascript_exponentation_operator.md create mode 100644 content/wiki/20201112111910-named_arguments.md create mode 100644 content/wiki/20201112113236-trailing_comma_in_parameter_lists.md create mode 100644 content/wiki/20201112120118-symfony_4_3.md create mode 100644 content/wiki/20201112120358-symfony_console_hyperlinks.md create mode 100644 content/wiki/20201112121020-symfony_il8n.md create mode 100644 content/wiki/20201112121416-always_include_route_default_values.md create mode 100644 content/wiki/20201112121938-symfony_constraints.md create mode 100644 content/wiki/20201112122929-bic_constraint.md create mode 100644 content/wiki/20201112123244-validate_bic_and_iban_codes_together.md create mode 100644 content/wiki/20201112123704-cardscheme_constraint.md create mode 100644 content/wiki/20201112124159-deprecating_service_aliases.md create mode 100644 content/wiki/20201112124304-symfony_services.md create mode 100644 content/wiki/20201112124715-symfony_configuration.md create mode 100644 content/wiki/20201112124832-automatic_search_engine_protection.md create mode 100644 content/wiki/20201112125413-configurable_session_id.md create mode 100644 content/wiki/20201112125637-symfony_json_constraint.md create mode 100644 content/wiki/20201112125813-symfony_json.md create mode 100644 content/wiki/20201112130234-symfony_console_iterable_progress_bars.md create mode 100644 content/wiki/20201112130435-iterate_method.md create mode 100644 content/wiki/20201112130710-notblank_constraint.md create mode 100644 content/wiki/20201112130816-notblank_allownull.md create mode 100644 content/wiki/20201112131310-configuring_services_with_immutable_setters.md create mode 100644 content/wiki/20201112131845-doctrine.md create mode 100644 content/wiki/20201112132007-automatic_validation_based_on_doctrine_mapping.md create mode 100644 content/wiki/20201112132331-unique_constraint.md create mode 100644 content/wiki/20201112132747-utf8_routing_option.md create mode 100644 content/wiki/20201112132858-symfony_utf_8_support.md create mode 100644 content/wiki/20201112133603-symfony_passwords.md create mode 100644 content/wiki/20201112133736-sodium_password_encoder.md create mode 100644 content/wiki/20201112134545-timezone_constraint.md create mode 100644 content/wiki/20201112134545-timezozne_constraint.md create mode 100644 content/wiki/20201112134752-compromised_password_constraint.md create mode 100644 content/wiki/20201112135249-mailer_component.md create mode 100644 content/wiki/20201112135851-symfony_native_encoder.md create mode 100644 content/wiki/20201112140448-httpclient_component.md create mode 100644 content/wiki/20201112140650-mime_component.md create mode 100644 content/wiki/20201112140917-number_constraints.md create mode 100644 content/wiki/20201113090050-javascript_object_operators.md create mode 100644 content/wiki/20201113090337-javascript_in_operator.md create mode 100644 content/wiki/20201113091110-javascript_object_properties.md create mode 100644 content/wiki/20201113091424-javascript_prototypes.md create mode 100644 content/wiki/20201113092454-javascript_symbols.md create mode 100644 content/wiki/20201113092902-javascript_primitives.md create mode 100644 content/wiki/20201113093204-javascript_object_prototype_methods.md create mode 100644 content/wiki/20201113093613-javascript_object_keywords.md create mode 100644 content/wiki/20201113093910-javascript_new_keyword.md create mode 100644 content/wiki/20201113094246-javascript_instanceof_operator.md create mode 100644 content/wiki/20201113094652-javascript_delete_operator.md create mode 100644 content/wiki/20201113095226-object_keys.md create mode 100644 content/wiki/20201113095244-object_assign.md create mode 100644 content/wiki/20201113095300-object_is.md create mode 100644 content/wiki/20201113102048-object_entries.md create mode 100644 content/wiki/20201113102106-object_values.md create mode 100644 content/wiki/20201113102125-object_getownpropertydescriptors.md create mode 100644 content/wiki/20201113103917-javascript_array_functions.md create mode 100644 content/wiki/20201113104217-array_prototype_fill.md create mode 100644 content/wiki/20201113104240-array_prototype_copywithin.md create mode 100644 content/wiki/20201113104332-array_prototype_findindex.md create mode 100644 content/wiki/20201113104352-array_prototype_find.md create mode 100644 content/wiki/20201113104423-array_prototype_entries.md create mode 100644 content/wiki/20201113104438-array_prototype_values.md create mode 100644 content/wiki/20201113104454-array_prototype_keys.md create mode 100644 content/wiki/20201113104552-array_search_prototype_methods.md create mode 100644 content/wiki/20201113104619-array_iteration_prototype_methods.md create mode 100644 content/wiki/20201113105707-array_prototype_includes.md create mode 100644 content/wiki/20201113105832-array_from.md create mode 100644 content/wiki/20201113105847-array_of.md create mode 100644 content/wiki/20201113111815-es2019.md create mode 100644 content/wiki/20201113112029-array_prototype_flat.md create mode 100644 content/wiki/20201113112058-array_prototype_flatmap.md create mode 100644 content/wiki/20201113113141-array_prototype_map.md create mode 100644 content/wiki/20201113115201-php_string_functions.md create mode 100644 content/wiki/20201113115231-str_contains.md create mode 100644 content/wiki/20201113115424-str_starts_with.md create mode 100644 content/wiki/20201113115452-str_ends_with.md create mode 100644 content/wiki/20201113115907-php_type_functions.md create mode 100644 content/wiki/20201113115939-get_debug_type.md create mode 100644 content/wiki/20201113120212-php_resource_functions.md create mode 100644 content/wiki/20201113120246-get_resource_id.md create mode 100644 content/wiki/20201113121741-php_expressions.md create mode 100644 content/wiki/20201113121813-match_expression.md create mode 100644 content/wiki/20201113122000-switch_expression.md create mode 100644 content/wiki/20201113122505-php_types.md create mode 100644 content/wiki/20201113122801-php_functions.md create mode 100644 content/wiki/20201113122959-php_mixed_type.md create mode 100644 content/wiki/20201113123224-php_objects.md create mode 100644 content/wiki/20201113123254-datetime.md create mode 100644 content/wiki/20201113123327-createfrominterface.md create mode 100644 content/wiki/20201113123648-createfromimmutable.md create mode 100644 content/wiki/20201113172025-symfony_5_0.md create mode 100644 content/wiki/20201113172517-type_constraint.md create mode 100644 content/wiki/20201113172816-type_constraint_can_be_an_array_of_types.md create mode 100644 content/wiki/20201113173159-signing_and_encrypting_messages.md create mode 100644 content/wiki/20201113174016-notification_emails.md create mode 100644 content/wiki/20201113174255-encryption.md create mode 100644 content/wiki/20201113174444-ecrypted_secrets_management.md create mode 100644 content/wiki/20201113175016-events.md create mode 100644 content/wiki/20201113175145-listeners.md create mode 100644 content/wiki/20201113175249-subscribers.md create mode 100644 content/wiki/20201113175527-event_listeners.md create mode 100644 content/wiki/20201113180227-simpler_event_listeners.md create mode 100644 content/wiki/20201113180551-doctrine_entity_listeners.md create mode 100644 content/wiki/20201113180722-invokable_doctrine_entity_listeners.md create mode 100644 content/wiki/20201113180928-horizontal_tables.md create mode 100644 content/wiki/20201113181152-symfony_style_for_commands.md create mode 100644 content/wiki/20201113181235-horizontaltable.md create mode 100644 content/wiki/20201113181356-definition_lists.md create mode 100644 content/wiki/20201113181759-password_migrations.md create mode 100644 content/wiki/20201113182438-httpfoundation_component.md create mode 100644 content/wiki/20201113182523-ip_address_anonymizer.md create mode 100644 content/wiki/20201113182753-week_form_type.md create mode 100644 content/wiki/20201113183038-lazy_firewalls.md create mode 100644 content/wiki/20201113183209-symfony_firewalls.md create mode 100644 content/wiki/20201113183442-string_component.md create mode 100644 content/wiki/20201113183442-symfony_string_component.md create mode 100644 content/wiki/20201114101358-quotes.md create mode 100644 content/wiki/20201114101614-you_can_t_have_this_kind_of_war_there_aren_t_enough_bulldozers_to_scrape_the_bodies_off_the_streets.md create mode 100644 content/wiki/20201114101721-political_science.md create mode 100644 content/wiki/20201114101926-american_presidents.md create mode 100644 content/wiki/20201114102043-dwight_d_eisenhower.md create mode 100644 content/wiki/20201114102140-nuclear_war.md create mode 100644 content/wiki/20201115141421-conventional_changelog.md create mode 100644 content/wiki/20201115141620-commit_guidelines.md create mode 100644 content/wiki/20201116095124-object_fromentries.md create mode 100644 content/wiki/20201116100205-trimstart.md create mode 100644 content/wiki/20201116100239-trimend.md create mode 100644 content/wiki/20201116100345-trim.md create mode 100644 content/wiki/20201116100926-characters_that_count_as_whitespace.md create mode 100644 content/wiki/20201116101443-javascript_symbol_prototype_methods.md create mode 100644 content/wiki/20201116101509-symbol_prototype_description.md create mode 100644 content/wiki/20201116105919-symfony_5_1.md create mode 100644 content/wiki/20201116121447-symfony_security.md create mode 100644 content/wiki/20201116121519-symfony_security_attributes.md create mode 100644 content/wiki/20201116121636-is_authenticated_remembered.md create mode 100644 content/wiki/20201116121711-is_authenticated_fully.md create mode 100644 content/wiki/20201116121759-is_remembered.md create mode 100644 content/wiki/20201116122125-role_previous_admin.md create mode 100644 content/wiki/20201116122525-is_impersonator.md create mode 100644 content/wiki/20201116123857-route_annotations_priority.md create mode 100644 content/wiki/20201116124210-compound_constraint.md create mode 100644 content/wiki/20201116124823-sequentially_constraint.md create mode 100644 content/wiki/20201116125148-single_command_applications.md create mode 100644 content/wiki/20201116125716-stringable_interface.md create mode 100644 content/wiki/20201116130210-truncate.md create mode 100644 content/wiki/20201116130327-keep_last_word.md create mode 100644 content/wiki/20201116130503-containsany.md create mode 100644 content/wiki/20201116130738-reverse.md create mode 100644 content/wiki/20201116131057-stateless.md create mode 100644 content/wiki/20201116131633-use_env_vars_in_route_conditions.md create mode 100644 content/wiki/20201116131815-symfony_uuid_component.md create mode 100644 content/wiki/20201116132411-hostname_constraint.md create mode 100644 content/wiki/20201116132826-service_decoration.md create mode 100644 content/wiki/20201116133113-stack_decorators.md create mode 100644 content/wiki/20201116133423-simpler_service_decoration.md create mode 100644 content/wiki/20201116133627-different_hosts_per_locale.md create mode 100644 content/wiki/20201116133907-logoutevent.md create mode 100644 content/wiki/20201116134142-console_cursor_control.md create mode 100644 content/wiki/20201116134435-atleastoneof_constraint.md create mode 100644 content/wiki/20201116134758-deprecate_public_services_into_private_services.md create mode 100644 content/wiki/20201116135523-expressionlanguagesyntax_constraint.md create mode 100644 content/wiki/20201116135741-expressionlanguage_component.md create mode 100644 content/wiki/20201116135915-expression_linter.md create mode 100644 content/wiki/20201116140434-ignore.md create mode 100644 content/wiki/20201116140847-symfony_contracts_component.md create mode 100644 content/wiki/20201116140934-trigger_depcreation.md create mode 100644 content/wiki/20201116141232-lint_yaml.md create mode 100644 content/wiki/20201116141414-linters.md create mode 100644 content/wiki/20201116141657-command_success.md create mode 100644 content/wiki/20201116141817-command_error.md create mode 100644 content/wiki/20201116142023-filesystem_component.md create mode 100644 content/wiki/20201116142105-tempnam.md create mode 100644 content/wiki/20201116142317-fromrandom.md create mode 100644 content/wiki/20201116142601-optionsresolver_component.md create mode 100644 content/wiki/20201116142709-define.md create mode 100644 content/wiki/20201116142916-symfony_resolver.md create mode 100644 content/wiki/20201116143004-info_setinfo.md create mode 100644 content/wiki/20201116143401-symfony_security_voters.md create mode 100644 content/wiki/20201116143526-affirmative.md create mode 100644 content/wiki/20201116143625-consensus.md create mode 100644 content/wiki/20201116143708-unanimous.md create mode 100644 content/wiki/20201116143740-priority.md create mode 100644 content/wiki/20201116154444-javascript_catch_binding.md create mode 100644 content/wiki/20201116154824-javascript_optional_catch_binding.md create mode 100644 content/wiki/20201116155459-array_prototype_sort.md create mode 100644 content/wiki/20201116155810-sort_is_guaranteed_to_be_stable.md create mode 100644 content/wiki/20201116162058-es2020.md create mode 100644 content/wiki/20201116162237-nullish_coalescing_operator.md create mode 100644 content/wiki/20201116162628-optional_chaining_operator.md create mode 100644 content/wiki/20201116163327-promise_allsettled.md create mode 100644 content/wiki/20201116163755-fractional_numbers.md create mode 100644 content/wiki/20201116163844-scientific_notation.md create mode 100644 content/wiki/20201116163925-infinity.md create mode 100644 content/wiki/20201116164007-nan.md create mode 100644 content/wiki/20201116164748-binary_notation.md create mode 100644 content/wiki/20201116164828-octal_notation.md create mode 100644 content/wiki/20201116165324-matchall_expression.md create mode 100644 content/wiki/20201116165819-javascript_bigint.md create mode 100644 content/wiki/20201116170151-dynamic_import.md create mode 100644 content/wiki/20201116170347-module_namespace_exports.md create mode 100644 content/wiki/20201116170538-globalthis.md create mode 100644 content/wiki/20201116182958-indolent.md create mode 100644 content/wiki/20201117095953-symfony_5_2.md create mode 100644 content/wiki/20201117100112-pseudo_localization_translator.md create mode 100644 content/wiki/20201117100855-true_console_colours.md create mode 100644 content/wiki/20201117101232-symfony_doctrine_integration.md create mode 100644 content/wiki/20201117101452-uuid_ulid_types.md create mode 100644 content/wiki/20201117102242-syfony_controller.md create mode 100644 content/wiki/20201117102440-symfony_controller_argument_attributes.md create mode 100644 content/wiki/20201117102746-currentuser.md create mode 100644 content/wiki/20201117103021-symfony_user.md create mode 100644 content/wiki/20201117103506-callback_functions_to_get_set_form_fields.md create mode 100644 content/wiki/20201117103957-uuid_normalizer.md create mode 100644 content/wiki/20201117104332-ulid_constraint.md create mode 100644 content/wiki/20201117104659-dkim_email_authentication.md create mode 100644 content/wiki/20201117105045-rout.md create mode 100644 content/wiki/20201117105314-symfony_routing_attributes.md create mode 100644 content/wiki/20201117105617-symfony_routing_annotations.md create mode 100644 content/wiki/20201117110902-symfony_doctrine_annotations.md create mode 100644 content/wiki/20201117111410-symfony_attributes.md create mode 100644 content/wiki/20201117111757-required.md create mode 100644 content/wiki/20201117112017-required.md create mode 100644 content/wiki/20201117112727-define_constraints_as_attributes.md create mode 100644 content/wiki/20201117113404-symfony_ratelimiter_component.md create mode 100644 content/wiki/20201117114036-login_throttling.md create mode 100644 content/wiki/20201117114443-front_controller_configuration.md create mode 100644 content/wiki/20201117114930-console_signals.md create mode 100644 content/wiki/20201117115146-consoleevents_signal.md create mode 100644 content/wiki/20201119165257-rust_1_48.md create mode 100644 content/wiki/20201119165454-rustdoc.md create mode 100644 content/wiki/20201119165530-rust_tooling.md create mode 100644 content/wiki/20201119170237-linking_to_items_by_name.md create mode 100644 content/wiki/20201119170710-search_aliases.md create mode 100644 content/wiki/20201119171245-tryinto.md create mode 100644 content/wiki/20201120094652-cargo_toml.md create mode 100644 content/wiki/20201120095606-slice.md create mode 100644 content/wiki/20201120095639-rust_primitive_types.md create mode 100644 content/wiki/20201120095739-as_ptr_range.md create mode 100644 content/wiki/20201120101047-as_mut_ptr_range.md create mode 100644 content/wiki/20201120102004-rust_pointers.md create mode 100644 content/wiki/20201120103547-rust_traits.md create mode 100644 content/wiki/20201120103613-trait_std.md create mode 100644 content/wiki/20201120103652-convert.md create mode 100644 content/wiki/20201120104659-turn_a_vector_into_an_array_of_a_given_length.md create mode 100644 content/wiki/20201120105306-rust_structs.md create mode 100644 content/wiki/20201120105504-struct_std.md create mode 100644 content/wiki/20201120105522-collections.md create mode 100644 content/wiki/20201120105602-vecdeque.md create mode 100644 content/wiki/20201120110719-rust_functions.md create mode 100644 content/wiki/20201120110752-function_std.md create mode 100644 content/wiki/20201120110819-future.md create mode 100644 content/wiki/20201120110842-pending.md create mode 100644 content/wiki/20201120111157-ready.md create mode 100644 content/wiki/20201121083531-movie_ideas.md create mode 100644 content/wiki/20201123094735-typescript_4_1.md create mode 100644 content/wiki/20201123100551-typescript_string_literal_type.md create mode 100644 content/wiki/20201123100939-typescript_boolean_literal_type.md create mode 100644 content/wiki/20201123101123-typescript_number_literal_type.md create mode 100644 content/wiki/20201123101810-typescript_template_literal_string_type.md create mode 100644 content/wiki/20201123103250-uppercase.md create mode 100644 content/wiki/20201123103315-lowercase.md create mode 100644 content/wiki/20201123103333-capitalize.md create mode 100644 content/wiki/20201123103400-uncapitalize.md create mode 100644 content/wiki/20201124085335-typescript_mapped_type.md create mode 100644 content/wiki/20201124090450-typescript_in_operator.md create mode 100644 content/wiki/20201124091025-typescript_literal_type_guard.md create mode 100644 content/wiki/20201124091530-typescript_strictnullchecks.md create mode 100644 content/wiki/20201124091740-typescript_user_defined_type_guards.md create mode 100644 content/wiki/20201124095453-typescript_as_clause.md create mode 100644 content/wiki/20201125085727-typescript_recursive_conditional_types.md create mode 100644 content/wiki/20201126095254-programming_terms.md create mode 100644 content/wiki/20201126095525-idempotent.md create mode 100644 content/wiki/20201126100331-ephemeral.md create mode 100644 content/wiki/20201126100942-anonymous.md create mode 100644 content/wiki/20201126101327-predicate.md create mode 100644 content/wiki/20201126101955-memoization.md create mode 100644 content/wiki/20201126102708-abstraction.md create mode 100644 content/wiki/20201126103142-serialization.md create mode 100644 content/wiki/20201126104931-nouncheckedindexaccess.md create mode 100644 content/wiki/20201127100908-checkjs.md create mode 100644 content/wiki/20201127100938-allowjs.md create mode 100644 content/wiki/20201127101043-typescript_flags.md create mode 100644 content/wiki/20201127101336-checkjs.md create mode 100644 content/wiki/20201130084544-react.md create mode 100644 content/wiki/20201130084608-react_factory_functions.md create mode 100644 content/wiki/20201130084644-jsx_react_factory_function.md create mode 100644 content/wiki/20201130084716-jsxs_react_factory_function.md create mode 100644 content/wiki/20201130085124-typescript_jsx_flag.md create mode 100644 content/wiki/20201130085253-react_jsx.md create mode 100644 content/wiki/20201130085317-react_jsxdev.md create mode 100644 content/wiki/20210405114813-technical_debt.md create mode 100644 content/wiki/20210405114931-code_debt.md create mode 100644 content/wiki/20210405115333-design_debt.md create mode 100644 content/wiki/20210405115411-test_debt.md create mode 100644 content/wiki/20210405115459-documentation_debt.md create mode 100644 content/wiki/20210405120239-software_design.md create mode 100644 content/wiki/20210405120426-important_quality_attributes_and_their_definitions.md create mode 100644 content/wiki/20210405121351-impact_of_multifaceted_abstraction_on_key_quality_attributes.md create mode 100644 content/wiki/20210405123214-viscosity.md create mode 100644 content/wiki/20211015195242-development_tools.md create mode 100644 content/wiki/20220212123754-gitlab.md create mode 100644 content/wiki/20220219131642-ipv6.md create mode 100644 content/wiki/20220507130634-pournelle_s_iron_law_of_bureaucracy.md create mode 100644 content/wiki/20220507131835-ci_cd.md create mode 100644 content/wiki/20220507132217-dns.md create mode 100644 content/wiki/20220507132251-stubby.md create mode 100644 content/wiki/20220507132657-dnscrypt.md create mode 100644 content/wiki/20220917160601-tawdry.md create mode 100644 content/wiki/index.md diff --git a/content/wiki/20200613170532-variable_types_in_javascript.md b/content/wiki/20200613170532-variable_types_in_javascript.md new file mode 100644 index 0000000..229cfff --- /dev/null +++ b/content/wiki/20200613170532-variable_types_in_javascript.md @@ -0,0 +1,161 @@ +--- +date: 2020-06-13 +id: 8af0e4ee-b090-4903-9ab7-020a4b7328ef +title: JavaScript Variables +--- + +# Types + +## Numbers + +JavaScript uses 64 bits to store number values + +### Fractional numbers + +``` javascript +console.log(9.81) +``` + +### Scientific notation + +``` javascript +console.log(2.998e8) +``` + +### Special Numbers + +1. Infinity + + Infinity and -Infinity represent positive and negative infinities + + ``` javascript + console.log(Infinity - 1) + console.log(Infinity + 1) + console.log(-Infinity - 1) + console.log(-Infinity + 1) + ``` + +2. NaN + + Not a number. The returned result if you try to do mathematical + nonsense + + ``` javascript + console.log(0/0) + console.log(Infinity - Infinity) + ``` + +## Strings + +Following are acceptable strings + +``` javascript +console.log(`Down on the sea`) +console.log("Lie on the ocean") +console.log('Float on the ocean') +``` + +Backslash escapes characters + +``` javascript +console.log("This is the first line\nAnd this is the second") +console.log("A newline character is written like \"\\n\".") +``` + +Backtick quoted strings ([template +literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)) +can span lines and also embed other values. \${} in a template literal +will be computed and converted to a string + +``` javascript +console.log(`This is a +backtick quotes string`) +console.log(`half of 100 is ${100 / 2}`) +``` + +## Boolean + +``` javascript +console.log(3 > 2) +console.log(3 < 2) +``` + +Strings can also be compared + +``` javascript +console.log("Aardvark" < "Zoroaster") +``` + +Uppercase characters are always less than lower case characters, so "Z" +\< "a". Non alphabetic characters are less than alphabetic characters + +``` javascript +console.log("Zebra" < "aardvark") +console.log("!" < "aardvark") +console.log("!" < "Zebra") +console.log("3" < "Zebra") +console.log("!" < "3") +``` + +## Empty values + +There are two special empty values, null & undefined that denote the +absence of any meaningful value. They can be used interchangeably and +are an [accident of JavaScripts +design](https://medium.com/@stephenthecurt/a-brief-history-of-null-and-undefined-in-javascript-c283caab662e). + +``` javascript +console.log(null == undefined); +``` + +# ES6 + +## Symbols + +They are tokens that serve as unique IDs. You create symbols via the +factory function Symbol() (which is loosely similar to String returning +strings if called as a function): + +``` javascript +const symbol1 = Symbol(); +``` + +### Add a description + +``` javascript +const tralala = Symbol('tralala') +console.log(tralala) // Symbol(tralala) +``` + +### Convert to string + +``` javascript +const tralala = Symbol('tralala') +console.log(String(tralala)) // `Symbol(tralala)` +``` + +### Every Symbol is unique + +``` javascript +console.log(Symbol() === Symbol()) // false +``` + +### Property keys + +``` javascript +const KEY = Symbol(); +const obj = {}; + +obj[KEY] = 123; +console.log(obj[KEY]); // 123 +``` + +``` javascript +const FOO = Symbol(); +const obj = { + [FOO]() { + return 'bar'; + } +}; +console.log(obj[FOO]()); // bar +``` diff --git a/content/wiki/20200613170705-operators_in_javascript.md b/content/wiki/20200613170705-operators_in_javascript.md new file mode 100644 index 0000000..880eab4 --- /dev/null +++ b/content/wiki/20200613170705-operators_in_javascript.md @@ -0,0 +1,27 @@ +--- +date: 2020-06-13 +id: a8f1290e-b4ef-4f80-bc21-69ddb4c22aca +title: JavaScript Operators +--- + +# Operators + +- [Arithmetic + Operators](20201112103849-javascript_arithmetic_operators) +- [Comparison + Operators](20201112105310-javascript_comparison_operators) +- [Conditional (Ternary) + Operator](20201112110025-javascript_conditional_ternary_operator) +- [Nullish coalescing operator + (??)](20201116162237-nullish_coalescing_operator) +- [Optional Chaining Operator + (?.)](20201116162628-optional_chaining_operator) +- [Object Operators](20201113090050-javascript_object_operators) +- [String Operators](20201112104819-javascript_string_operators) +- [Unary Operators](20201112105050-javascript_unary_operators) + +# Logical operators + +- [Logical Operators](20201112105647-javascript_logical_operators) +- [Short Circuiting of Logical + Operators](20201112105833-javascript_short_circuiting_of_logical_operators) diff --git a/content/wiki/20200613170756-javascript_type_conversion.md b/content/wiki/20200613170756-javascript_type_conversion.md new file mode 100644 index 0000000..835a53d --- /dev/null +++ b/content/wiki/20200613170756-javascript_type_conversion.md @@ -0,0 +1,17 @@ +--- +date: 2020-06-13 +id: 9e542d77-7a1f-4f6b-a48d-ce12afc68101 +title: JavaScript Type Conversion +--- + +# Syntax + +``` javascript +console.log(8 * null) +console.log("5" - 1) +console.log("5" + 1) +console.log("five" * 2) +console.log(false == 0) +console.log(false == "") +console.log(null == 0) +``` diff --git a/content/wiki/20200613170756-type_conversion_in_javascript.md b/content/wiki/20200613170756-type_conversion_in_javascript.md new file mode 100644 index 0000000..d7f6a8a --- /dev/null +++ b/content/wiki/20200613170756-type_conversion_in_javascript.md @@ -0,0 +1,17 @@ +--- +date: 2020-06-13 +id: cc70a2c4-2d57-4a17-8c52-ba5f143d830c +title: Type conversion in JavaScript +--- + +# Type conversion + +``` javascript +console.log(8 * null) +console.log("5" - 1) +console.log("5" + 1) +console.log("five" * 2) +console.log(false == 0) +console.log(false == "") +console.log(null == 0) +``` diff --git a/content/wiki/20200613170905-javascript.md b/content/wiki/20200613170905-javascript.md new file mode 100644 index 0000000..2e1ad54 --- /dev/null +++ b/content/wiki/20200613170905-javascript.md @@ -0,0 +1,135 @@ +--- +date: 2020-06-13 +id: 6adaacc0-8c1e-4fb3-99c2-50db5bcbfa6b +title: JavaScript +--- + +# Language + +## Objects + +- [Arrays](20200826201029-arrays) +- [Objects](20200826201605-objects) + +## Types + +- [Numbers](20200922164416-numbers) +- [Strings](20200922164551-strings) +- [Booleans](20200922164727-booleans) +- [Empty values](20200922164830-empty_values) +- [Numbers](20200922164416-numbers) +- [BigInt](20201116165819-javascript_bigint) + +## Values Operators + +- [Operators](20200613170705-operators_in_javascript) +- [Type Conversion](20200613170756-javascript_type_conversion) +- [Destructuring](20200922160850-destructuring) +- [Spread (…)](20201014094144-spread) + +## Program Structure + +- [Binding / + Variables](20200613172137-binding_variables_in_javascript) +- [Control flows](20200613172534-javascript_control_flows) + +## Functions + +- [Bindings and scopes](20200702203250-bindings_and_scopes) +- [Closure](20200702204351-closure) +- [Recursion](20200702204437-recursion) +- [Higher-order functions](20200827142818-higher_order_functions) +- [Generators](20200911155947-generators) + +### Definitions + +- [Function + Declarations](20201006111125-javascript_function_declerations) +- [Declaration notation](20201006111244-declaration_notation) +- [Arrow Functions](20201006111349-arrow_functions) + +### Parameters + +- [Optional arguments](20200702204226-optional_arguments) +- [Parameter default values](20200922162003-parameter_default_values) +- [Named parameters](20200922162127-named_parameters) +- [Rest parameters](20200922162500-rest_parameters) + +## Classes + +- [Class Notation](20201008090316-class_notation) +- [Method Definition](20201008090449-method_definition) +- [Inheritance](20201008090613-inheritance) +- [Getters & + setters](20201007093418-javascript_object_getters_setters) + +## Structures + +- [Maps](20201012093745-javascript_maps) +- [WeakMaps](20201012094749-javascript_weakmaps) +- [Sets](20201012094248-javascript_sets) + +## Standard Libraries + +- [Error handling](20200901105237-error_handling) +- [Regular expressions](20200902162305-regular_expressions) +- [Number](20200923153425-number) +- [Math](20200923153614-math) + +## Modules + +- [CommonJS](20200916172802-commonjs) +- [ECMAScript](20200916172914-ecmascript) + +## Asynchronous Programming + +- [Callbacks](20200911150451-callbacks) +- [Promises](20200911154351-promises) +- [Async functions](20201026103714-javascript_async_functions) + +## Iterables & Iterators + +- [Iterables](20201014092625-javascript_iterables) +- [Iterator](20201014092846-javascript_iterator) +- [Async Iterator](20201030092200-javascript_async_iterator) + +## Metaprogramming + +- [Proxies](20201022094207-javascript_proxies) +- [Metaprogramming](20201022095438-javascript_metaprogramming) + +## Comments + +- [Comments](20201030094749-javascript_comments) + +## Rest / Spread Properties + +- [Rest Operator (…) in Object + Destructuring](20201103111357-rest_operator_in_object_destructuring) + +## Imports + +- [Dynamic Import](20201116170151-dynamic_import) +- [Module Namespace Exports](20201116170347-module_namespace_exports) + +## Misc + +- [globalThis](20201116170538-globalthis) + +# Frameworks + +- [Vue.js](20201021141613-vue_js) +- [React](20201130084544-react) + +# Changelog + +- [ES6](20201030093404-es6) +- [ES2016](20201023130243-es2016) +- [ES2017](20201026104538-es2017) +- [ES2018](20201030095105-es2018) +- [ES2019](20201113111815-es2019) +- [ES2020](20201116162058-es2020) + +# Sources + +- [Books](20200613170934-javascript_books) diff --git a/content/wiki/20200613170934-javascript_books.md b/content/wiki/20200613170934-javascript_books.md new file mode 100644 index 0000000..ab6dc3c --- /dev/null +++ b/content/wiki/20200613170934-javascript_books.md @@ -0,0 +1,14 @@ +--- +date: 2020-06-13 +id: 116e53fb-3830-473d-9474-57c8b45aa996 +title: JavaScript Books +--- + +# Some handy JavaScript books + +- [Eloquent JavaScript](https://eloquentjavascript.net/) +- [Exploring ES6](https://exploringjs.com/es6.html) +- [Exploring ES2016 and + ES2017](https://exploringjs.com/es2016-es2017.html) +- [Exploring ES2018 and + ES2019](https://exploringjs.com/es2018-es2019/index.html) diff --git a/content/wiki/20200613171743-javascript_types.md b/content/wiki/20200613171743-javascript_types.md new file mode 100644 index 0000000..5614320 --- /dev/null +++ b/content/wiki/20200613171743-javascript_types.md @@ -0,0 +1,84 @@ +--- +date: 2020-06-13 +id: cb93f6ba-527b-4602-b5f4-de0281897800 +title: JavaScript Types +--- + +# Numbers + +JavaScript uses 64 bits to store number values + +## Fractional numbers + +``` javascript +console.log(9.81) +``` + +## Scientific notation + +``` javascript +console.log(2.998e8) +``` + +## Special Numbers + +### Infinity + +Infinity and -Infinity represent positive and negative infinities + +``` javascript +console.log(Infinity - 1) +console.log(Infinity + 1) +console.log(-Infinity - 1) +console.log(-Infinity + 1) +``` + +### NaN + +Not a number. The returned result if you try to do mathematical nonsense + +``` javascript +console.log(0/0) +console.log(Infinity - Infinity) +``` + +# Boolean + +``` javascript +console.log(3 > 2) +console.log(3 < 2) +``` + +Strings can also be compared + +``` javascript +console.log("Aardvark" < "Zoroaster") +``` + +Uppercase characters are always less than lower case characters, so "Z" +\< "a". Non alphabetic characters are less than alphabetic characters + +``` javascript +console.log("Zebra" < "aardvark") +console.log("!" < "aardvark") +console.log("!" < "Zebra") +console.log("3" < "Zebra") +console.log("!" < "3") +``` + +# Empty values + +There are two special empty values, null & undefined that denote the +absence of any meaningful value. They can be used interchangeably and +are an [accident of JavaScripts +design](https://medium.com/@stephenthecurt/a-brief-history-of-null-and-undefined-in-javascript-c283caab662e). + +``` javascript +console.log(null == undefined); +``` + +# Related + +- [JavaScript](20200613170905-javascript) +- [Arrays](20200826201029-arrays) +- [Strings](20200922164551-strings) diff --git a/content/wiki/20200613172137-binding_variables_in_javascript.md b/content/wiki/20200613172137-binding_variables_in_javascript.md new file mode 100644 index 0000000..bc0bc04 --- /dev/null +++ b/content/wiki/20200613172137-binding_variables_in_javascript.md @@ -0,0 +1,46 @@ +--- +date: 2020-06-13 +id: 6efc70be-8154-420f-a92e-622ef1ad960c +title: Binding / Variables in JavaScript +--- + +# ES6 + +## Let + +``` javascript +let caught = 5 * 5 +console.log(caught) + +let mood = "light" +console.log(mood) +mood = "dark" +console.log(mood) + +let luigisDebt = 140; +luigisDebt = luigisDebt - 35; +console.log(luigisDebt); +``` + +A single let statement my define multiple bindings + +``` javascript +let one = 1, two = 2 +console.log(one + two) +``` + +## Const + +This is a constant binding. It points to the same value for as long as +it lives + +``` javascript +const blaat = "abcd" +console.log(blaat) +/** + * Following will both cause errors: + * + * blaat = "efgh" + * let blaat = "efgh" +*/ +``` diff --git a/content/wiki/20200613172534-control_flows_in_javascript.md b/content/wiki/20200613172534-control_flows_in_javascript.md new file mode 100644 index 0000000..e5149af --- /dev/null +++ b/content/wiki/20200613172534-control_flows_in_javascript.md @@ -0,0 +1,132 @@ +--- +date: 2020-06-13 +id: adffc782-d978-49f3-9367-33e77b05af8a +title: Control flows in JavaScript +--- + +# ES6 + +## for-of + +``` javascript +const arr = ['a', 'b', 'c']; +for (const elem of arr) { + console.log(elem); +} +``` + +``` javascript +const arr = ['a', 'b', 'c']; +for (const [index, elem] of arr.entries()) { + console.log(index+'. '+elem); +} +``` + +# if statement + +``` javascript +if(true === true) { + console.log("True is true") +} + +if (true === false) { + console.log("True is false") +} +else { + console.log("True is not false") +} +``` + +# while statement + +``` javascript +let i = 0 +while (i <= 5) { + console.log("Loop " + i) + i++ +} + +let j = 0 +do { + j++ +} while (j <= 5) +console.log("Do while j value is " + j) +``` + +# for statement + +``` javascript +for(let k = 0; k <= 5; k++) { + console.log("For loop k " + k) +} +``` + +# switch statement + +``` javascript +switch ("rainy") { + case "rainy": + console.log("Remember to bring an umbrella."); + break; + case "sunny": + console.log("Dress lightly."); + case "cloudy": + console.log("Go outside."); + break; + default: + console.log("Unknown weather type!"); + break; +} + +switch ("sunny") { + case "rainy": + console.log("Remember to bring an umbrella."); + break; + case "sunny": + console.log("Dress lightly."); + case "cloudy": + console.log("Go outside."); + break; + default: + console.log("Unknown weather type!"); + break; +} + +switch ("wild card") { + case "rainy": + console.log("Remember to bring an umbrella."); + break; + case "sunny": + console.log("Dress lightly."); + case "cloudy": + console.log("Go outside."); + break; + default: + console.log("Unknown weather type!"); + break; +} +``` + +# Breaking out of a loop + +``` javascript +for (let current = 20; ; current = current + 1) { + if (current % 7 == 0) { + console.log(current); + break; + } +} +``` + +# Comments + +``` javascript +// This is a one line comment +let i = 0 + +/** + This is a multi line comment + Here is the second line +*/ +let j = 0 +``` diff --git a/content/wiki/20200613172534-javascript_control_flows.md b/content/wiki/20200613172534-javascript_control_flows.md new file mode 100644 index 0000000..8ffcd1a --- /dev/null +++ b/content/wiki/20200613172534-javascript_control_flows.md @@ -0,0 +1,26 @@ +--- +date: 2020-06-13 +id: 65258dfb-bf3f-454a-8219-a22a29cb1683 +title: JavaScript Control Flows +--- + +# Statements + +- [if statement](20201030093832-javascript_if_statement) +- [while statement](20201030093956-javascript_while_statement) +- [for statement](20201030094040-javascript_for_statement) +- [for await of](20201030095741-javascript_for_await_of) +- [for of statement](20201030093304-javascript_for_of) +- [switch statement](20201030094138-javascript_switch_statement) +- [try catch](20201116154444-javascript_catch_binding) + +# Catch binding + +- [Catch Binding](20201116154444-javascript_catch_binding) +- [Optional Catch + Binding](20201116154824-javascript_optional_catch_binding) + +# Misc + +- [Breaking out of a + loop](20201030094343-javascript_breaking_out_of_a_loop) diff --git a/content/wiki/20200702203250-bindings_and_scopes.md b/content/wiki/20200702203250-bindings_and_scopes.md new file mode 100644 index 0000000..5ef7b41 --- /dev/null +++ b/content/wiki/20200702203250-bindings_and_scopes.md @@ -0,0 +1,65 @@ +--- +date: 2020-07-02 +id: 40bc3b60-ab05-4ff6-a258-f5cb38322c77 +title: Bindings and scopes in JavaScript +--- + +# Bindings + +- For bindings defined outside of any function or block, the scope is + the whole program. We call these `global` bindings +- Bindings created for function parameters or declared inside a + function can only be referenced in that function. These are known as + `local` bindings. New instances of these `local` bindings are + created every time the function is called +- Bindings declared with `let` and `const` are local to the block that + they are declared in +- In pre-2015 JavaScript, only functions created new scopes. So + old-style bindings created with `var` are visible throughout the + whole function that they appear in. If not declared in a function + then scope is `global` + +``` javascript +let x = 10 +if (true) { + let y = 20 + var z = 30 + console.log(x + y + z) +} + +// y is not accessable here +console.log(x + z) +``` + +``` javascript +const halve = function(n) { + return n / 2 +} + +let n = 10 + +console.log(halve(100)) +console.log(n) +``` + +# Nested scope + +``` javascript +const hummus = function(factor) { + const ingredient = function(amount, unit, name) { + let ingredientAmount = amount * factor; + if (ingredientAmount > 1) { + unit += "s"; + } + console.log(`${ingredientAmount} ${unit} ${name}`); + }; + ingredient(1, "can", "chickpeas"); + ingredient(0.25, "cup", "tahini"); + ingredient(0.25, "cup", "lemon juice"); + ingredient(1, "clove", "garlic"); + ingredient(2, "tablespoon", "olive oil"); + ingredient(0.5, "teaspoon", "cumin"); +}; + +hummus(1) +``` diff --git a/content/wiki/20200702204226-optional_arguments.md b/content/wiki/20200702204226-optional_arguments.md new file mode 100644 index 0000000..10436e9 --- /dev/null +++ b/content/wiki/20200702204226-optional_arguments.md @@ -0,0 +1,40 @@ +--- +date: 2020-07-02 +id: 6e1019ae-983e-42c6-90cf-daa6aebb86ea +title: Optional arguments in JavaScript functions +--- + +JavaScript is extremely broad-minded about the number of arguments you +pass to a function. If you pass too many, the extra ones are ignored. If +you pass too few, the missing parameters get assigned the value +`undefined`. + +``` javascript +function square(x) { return x * x; } +console.log(square(4, true, "hedgehog")); +``` + +``` javascript +function minus(a, b) { + if (b === undefined) return -a; + else return a - b; +} + +console.log(minus(10)); +console.log(minus(10, 5)); +``` + +Function parameters can also be given default values + +``` javascript +function power(base, exponent = 2) { + let result = 1; + for (let count = 0; count < exponent; count++) { + result *= base; + } + return result; +} + +console.log(power(4)); +console.log(power(2, 6)); +``` diff --git a/content/wiki/20200702204351-closure.md b/content/wiki/20200702204351-closure.md new file mode 100644 index 0000000..2fc995f --- /dev/null +++ b/content/wiki/20200702204351-closure.md @@ -0,0 +1,35 @@ +--- +date: 2020-07-02 +id: 8659a753-2c0d-46cb-afdc-095e318aabff +title: Closure in JavaScript +--- + +Local bindings are created anew for every call, and different calls +can't affect on another calls local bindings. + +``` javascript +function wrapValue(n) { + let local = n; + return () => local; +} + +let wrap1 = wrapValue(1); +let wrap2 = wrapValue(2); +console.log(wrap1()); +console.log(wrap2()); +``` + +A function that references bindings from local scopes around it is +called a closure. This behavior not only frees you from having to worry +about lifetimes of bindings but also makes it possible to use function +values in some creative ways. + +``` javascript +function multiplier(factor) { + return number => number * factor; +} + +let twice = multiplier(2); + +console.log(twice(5)); +``` diff --git a/content/wiki/20200702204437-recursion.md b/content/wiki/20200702204437-recursion.md new file mode 100644 index 0000000..ddc8457 --- /dev/null +++ b/content/wiki/20200702204437-recursion.md @@ -0,0 +1,17 @@ +--- +date: 2020-07-02 +id: f77e6e36-1674-46b6-a8c9-d5a77d40f19e +title: Recursion in JavaScript +--- + +``` javascript +function power(base, exponent) { + if (exponent == 0) { + return 1; + } else { + return base * power(base, exponent - 1); + } +} + +console.log(power(2, 3)); +``` diff --git a/content/wiki/20200704151304-history.md b/content/wiki/20200704151304-history.md new file mode 100644 index 0000000..d10bdaa --- /dev/null +++ b/content/wiki/20200704151304-history.md @@ -0,0 +1,25 @@ +--- +date: 2020-07-04 +id: ed692a43-3267-4b5d-a0a7-cef4a25b4fda +title: History +--- + +# USSR + +- [Economic state of USSR + 1942-1943](20200704151508-economic_state_of_ussr_1942_1943) + +# Islamic History + +- [Stages of Islamic + History](20200706161134-stages_of_islamic_history) +- [The Chaldeans](20200706165803-the_chaldeans) + +# Western History + +- [Stages of Christian + history](20200706164411-stages_of_christian_history) + +# Misc + +- [Historical Terms](20201029195742-historical_terms) diff --git a/content/wiki/20200704151508-economic_state_of_ussr_1942_1943.md b/content/wiki/20200704151508-economic_state_of_ussr_1942_1943.md new file mode 100644 index 0000000..55e6fa2 --- /dev/null +++ b/content/wiki/20200704151508-economic_state_of_ussr_1942_1943.md @@ -0,0 +1,77 @@ +--- +date: 2020-07-04 +id: de009f15-07b5-4e76-8976-349c949bc148 +title: Economic state of USSR 1942-1943 +--- + +# Outline + +- Impossible to calculate as Soviet figures are unreliable at best. + Relying on convergence of anecdotal evidence +- Source - Economics of ww2 by Harrison +- Cats & dogs going missing in Moscow +- People going to the front because food is so bad at home +- 62nd/63rd/64th army running out of food +- Roosevelt tells Molatov in 42 that he'll send less food to start the + second front in 43 instead of 44. Molatov doesn't want this, he + prefers food +- Census is done in 37. Stalin didn't like the results and had the + people who did the census shot. Next census showed the correct + numbers +- In controlled communist economies prices of goods are made up by + government and are therefore meaningless +- Soviet Union were in dire economic straits. If Stalingrad was won by + the Germans they would probably have collapsed + +# Pre war economy + +## Agriculture + +| Country | Working population in agriculture | Output of non agricultural worker | +|----|----|----| +| USSR | 57% | 33% | +| Germany | 26% | 50% | +| USA | 17% | 40% | +| UK | 6% | 59% | + +- Agricultural workers in USSR were female because men were drafted + for the war or in gulags +- Amount of rubels spent on the economy dropped from 58.3bn in 1940 to + 31.6bn in 1942 +- Inflation was also rampant which amplified the problems +- Ukraine & caucuses were taken by Germany. the wheat basket +- Collectivised farms were terrible for productivity +- Soviet citizens average daily intake of calories from 1942-1943 is + estimated to have been 2555 calories. In 1944 this was increased to + 2810 calories. 500 calories less than average german/british + civilian. Americans ate 1000 more. +- Dispossed/hungry licked plates of others meals +- Communist leadership ate well +- 200-300 grams of sub standard bread +- Soviets ate half as much food as US citizens on average +- Zhukov boasted his men lived on 1000 calories / day during the + battle of Stalingrad +- between 1940-1942 real output of civilian branches feel from 1/2 to + 2/3 +- By 1942 agricultural output fell to 44% of pre war (1937) level + according to official Soviet numbers +- 50m people in USSR employed in agriculture in 1940. By 1942 figure + dropped to 25m according to official USSR numbers +- Half the population were covered by official rationing system +- 80% of the rations were bread +- After 1942 mortality rates in Siberia decreased because the weakest + already died off + +# Gulags + +- In gulags rations were decreased dramatically. from 1942-1943 people + were starving in gulags +- During war years 5m people were in gulag system. 1m were released to + the front. Majority left in gulags were ill and infirm. They were + given light work. Even before the war food wasn't provided in enough + quantities in 1939 +- camp mortality reached it peak in 1942 when 50k prisoners died every + month. +- Over 2m people died in gulags and camps during war years +- Household consumption by workers decreased by 2 fifths from + 1940-1942 diff --git a/content/wiki/20200704151715-economics.md b/content/wiki/20200704151715-economics.md new file mode 100644 index 0000000..71ab474 --- /dev/null +++ b/content/wiki/20200704151715-economics.md @@ -0,0 +1,8 @@ +--- +date: 2020-07-04 +id: 2e431131-c786-4718-964c-b0ff972de8da +title: Economics +--- + +- [Economic state of USSR + 1942-1943](20200704151508-economic_state_of_ussr_1942_1943) diff --git a/content/wiki/20200704151950-ledger.md b/content/wiki/20200704151950-ledger.md new file mode 100644 index 0000000..c8d73bc --- /dev/null +++ b/content/wiki/20200704151950-ledger.md @@ -0,0 +1,120 @@ +--- +date: 2020-07-04 +id: 38f9bc4b-06de-4f23-9626-3e4dad348dd3 +title: Ledger +--- + +# Common [Ledger](https://www.ledger-cli.org/) CLI Commands ([Source](https://gist.githubusercontent.com/agarrharr/03450c1be7f6b3d2b883c6b5e317d2aa/raw/4c5bfa57be1cd98a232e3f4bda0fcc2a51ba0862/index.md)) + +## Income vs expenses this month? + +``` bash +ledger balance income expenses --period "this month" +``` + +## What did my budget look like at a certain date? + +``` bash +ledger balance budget --end 2018-01-02 +``` + +This is how it looked at the end of the day on Jan 1, 2018. + +## How much is in the checking account right now? + +``` bash +ledger balance checking +``` + +## What is our net worth? + +``` bash +ledger balance ^assets ^liabilities --real +``` + +## How much money have we made? + +``` bash +ledger balance income +``` + +## How much money have we made from our salaries? + +``` bash +ledger balance income:salary +``` + +## How much do we spend each month on x? + +``` bash +ledger register -M expenses:groceries:food +``` + +## Group transactions by payee + +``` bash +ledger register --by-payee +``` + +## Only show uncleared transactions + +``` bash +ledger register --uncleared +``` + +## Do I have enough budgeted to pay off my credit cards? + +``` bash +ledger balance creditcard +``` + +It should be \$0.00. If it's not \$0.00, run this with different dates +to find the problem: + +``` bash +ledger balance creditcard --end 2018-02-01 +``` + +## Import + +Change Chase checking from: + +``` example +Details,Posting Date,Description,Amount,Type,Balance,Check or Slip # +``` + +to: + +``` example +,Date,Payee,Amount,,,Code +``` + +Change Chase Credit Card from: + +``` example +Type,Trans Date,Post Date,Description,Amount +``` + +to: + +``` example +,Date,Posted,Payee,Amount +``` + +``` bash +ledger convert ~/Downloads/checking.CSV --input-date-format "%m/%d/%Y" --invert --account Assets:Checking --rich-data -f budget.ledger --auto-match --pager less +``` + +## Expenses each month (sorted) + +``` bash +ledger -M --period-sort "(amount)" reg ^expenses +``` + +This will show all expenses, grouped by month and sorted by the amount. + +## How much do we spend on credit cards each month? + +``` bash +ledger -M -r --display 'account=~/creditcard/' reg ^expenses +``` diff --git a/content/wiki/20200704152249-vocabulary.md b/content/wiki/20200704152249-vocabulary.md new file mode 100644 index 0000000..df3acfe --- /dev/null +++ b/content/wiki/20200704152249-vocabulary.md @@ -0,0 +1,62 @@ +--- +date: 2020-07-04 +id: 726cec04-6f79-42e8-8677-63d8980f5ca4 +title: Vocabulary +--- + +# Categories + +- [Architecture](20201109123541-architecture) +- [Chess Terms](20201109120843-chess_terms) +- [Clothing](20201109123123-clothing) +- [Furniture](20201104090504-furniture) +- [Geographic Terms](20201029195945-geographic_terms) +- [Glassware](20201109123853-glassware) +- [Historical Terms](20201029195742-historical_terms) +- [Political science terms](20201029200040-political_science_terms) +- [Programming Terms](20201126095254-programming_terms) +- [Sexual terms](20201029200327-sexual_terms) +- [Tongue Twisters](20201109122104-tongue_twisters) + +# Adjectives, nouns & verbs + +- [Adjectives](20201029204304-adjectives) +- [Nouns](20201030183237-nouns) +- [Verbs](20201030182939-verbs) + +# Complete list + +- [anathema](20201109122445-anathema) +- [antecedent](20201030195742-antecedent) +- [antimacassar](20201109122731-antimacassar) +- [anteroom](20201109123452-anteroom) +- [bluestocking](20201029201415-bluestocking) +- [Carthaginian peace](20201029194838-carthaginian_peace) +- [chenille](20201109121858-chenille) +- [chiffonier](20201104090229-chiffonier) +- [decanter](20201109123736-decanter) +- [detritus](20201029195142-detritus) +- [eidetic](20201109124059-eidetic) +- [epaulet](20201109121407-epaulet) +- [fianchetto](20201109120912-fianchetto) +- [gaberdine](20201109123003-gaberdine) +- [geld](20201030183019-geld) +- [gregarious](20201029204128-gregarious) +- [imperturbable](20201109121645-imperturbable) +- [inchmeal](20201109124204-inchmeal) +- [indolent](20201116182958-indolent) +- [Intercommunicating zones](20201029195404-intercommunicating_zones) +- [insouciance](20201109121245-insouciance) +- [mirth](20201109121522-mirth) +- [percolate](20201109121108-percolate) +- [perfunctory](20201109122833-perfunctory) +- [podophilia](20201029200235-podophilia) +- [précis](20201109122314-precis) +- [prig](20201109122557-prig) +- [rancor](20201109123923-rancor) +- [sanguine](20201109123624-sanguine) +- [tawdry](20220917160601-tawdry) +- [Useful idiot](20201029195302-useful_idiot) +- [viscosity](20210405123214-viscosity) +- [wily](20201109121740-wily) +- [worsted](20201109123326-worsted) diff --git a/content/wiki/20200704152442-rust.md b/content/wiki/20200704152442-rust.md new file mode 100644 index 0000000..7d215b8 --- /dev/null +++ b/content/wiki/20200704152442-rust.md @@ -0,0 +1,66 @@ +--- +date: 2020-07-04 +id: 882564c6-4258-40f4-87ec-fb5b267b7ac2 +title: Rust +--- + +- [Rust Tooling](20201119165530-rust_tooling) + +# API + +- [Functions](20201120110719-rust_functions) +- [Primitive Types](20201120095639-rust_primitive_types) +- [Structs](20201120105306-rust_structs) +- [Traits](20201120103547-rust_traits) + +# Language + +- [Comments](20200827190035-rust_comments) +- [Control flow](20200827190443-rust_control_flow) +- [Enums](20200902150714-enums) +- [Iterators](20200923150006-iterators) +- [Ownership](20200828170945-ownership) +- [Pointers](20201120102004-rust_pointers) +- [Structs](20200831193417-structs) +- [Tests](20200918183524-tests) +- [Variables](20200827171554-variables_in_rust) + +## Common Collections + +- [Vectors](20200915140449-vectors) +- [Strings](20200915151358-strings) +- [Hash Maps](20200915153033-hash_maps) + +## Concurrency + +- [Threads](20200930121904-rust_threads) +- [Message passing](20200930123003-message_passing) +- [Shared-State + Concurrency](20200930123749-rust_shared_state_concurrency) + +## Error handling + +- [Unrecoverable Errors](20200916162727-unrecoverable_errors) +- [Recoverable Errors](20200916163737-recoverable_errors) + +## Functions + +- [Functions & macros](20200827170931-functions_macros) +- [Closures](20200923144022-closures) + +## Generic Types and Traits + +- [Generics](20200917161757-generics) +- [Traits](20200917163203-traits) + +## Patterns and Matching + +- [Pattern Syntax](20201006102934-pattern_syntax) + +# Misc + +- [Books & exercises](20200827171318-rust_books) + +# Changelog + +- [1.48](20201119165257-rust_1_48) diff --git a/content/wiki/20200706161134-stages_of_islamic_history.md b/content/wiki/20200706161134-stages_of_islamic_history.md new file mode 100644 index 0000000..e9ed39c --- /dev/null +++ b/content/wiki/20200706161134-stages_of_islamic_history.md @@ -0,0 +1,20 @@ +--- +date: 2020-07-06 +id: 61037644-f96f-4ab2-8ea5-4f8829b4de9c +title: The 10 stages of Islamic History +--- + +Islamic history can roughly be divided into 10 stages (as opposed to +[the 10 stages of Christian +history](20200706164411-stages_of_christian_history)): + +1. Ancient Times: Mesopotamia and Persia +2. Birth of Islam +3. The Caliphate: Quest for Universal Unity +4. Fragmentation: Age of the Sultanates +5. Catastrophe: Crusaders and Mongols +6. Rebirth: The Three-Empires Era +7. Permeation of East by West +8. The Reform Movements +9. Triumph of the Secular Modernists +10. The Islamist Reaction diff --git a/content/wiki/20200706164411-stages_of_christian_history.md b/content/wiki/20200706164411-stages_of_christian_history.md new file mode 100644 index 0000000..cebd398 --- /dev/null +++ b/content/wiki/20200706164411-stages_of_christian_history.md @@ -0,0 +1,22 @@ +--- +date: 2020-07-06 +id: baac5bf7-b54a-4fed-927b-e8a4f220e81c +title: The 10 stages of Christian history +--- + +When the ideal future envisioned by post industrialized, Western +democratic society is taken as the endpoint of history, the shape of the +narrative leading to here-and-now features something like the following +stages (as opposed to [the 10 stages of Islamic +history](20200706161134-stages_of_islamic_history)): + +1. Birth of civilization (Egypt and Mesopotamia) +2. Classical age (Greece and Rome) +3. The Dark Ages (rise of Christianity) +4. The Rebirth: Renaissance and Reformation +5. The Enlightenment (exploration and science) +6. The Revolutions (democratic, industrial, technological) +7. Rise of Nation-States: The Struggle for Empire +8. World Wars I and II. +9. The Cold War +10. The Triumph of Democratic Capitalism diff --git a/content/wiki/20200706165803-the_chaldeans.md b/content/wiki/20200706165803-the_chaldeans.md new file mode 100644 index 0000000..4a351b5 --- /dev/null +++ b/content/wiki/20200706165803-the_chaldeans.md @@ -0,0 +1,15 @@ +--- +date: 2020-07-06 +id: fcbdb286-af0e-484f-8a2d-dd5b2e18ff5b +title: The Chaldeans +--- + +The Assyrians fell at last to one of their subject peoples, the +Chaldeans, who rebuilt Babylon and won a lustrous place in history for +their intellectual achievements in astronomy, medicine, and mathematics. +They used a base-12 system (as opposed to our base-10 system) and were +pioneers in the measurement and division of time, which is why the year +has twelve months, the hour has sixty minutes (five times twelve), and +the minute has sixty seconds. They were terrific urban planners and +architects—it was a Chaldean king who built those Hanging Gardens of +Babylon, which the ancients ranked among the seven wonders of the world. diff --git a/content/wiki/20200826142641-golang.md b/content/wiki/20200826142641-golang.md new file mode 100644 index 0000000..40b1b1a --- /dev/null +++ b/content/wiki/20200826142641-golang.md @@ -0,0 +1,59 @@ +--- +date: 2020-08-26 +id: 3e8fc539-e90c-4278-a233-6158dbca89e4 +title: Golang +--- + +# Language + +## Basics + +- [Packages](20200826142755-packages) +- [Functions](20200826151337-functions) +- [Variables](20200826151514-variables) +- [Flow control statements](20200826151846-flow_control_statements) +- [Tests](20200826191127-tests) +- [Tooling](20200826191508-tooling) +- [Pointers](20200828180957-pointers) +- [Structs](20200828181259-structs) +- [Arrays](20200828182327-arrays) +- [Slices](20200828182546-slices) +- [Maps](20200828192034-maps) +- [Methods](20200831155304-methods) +- [Interfaces](20200831171822-interfaces) +- [Errors](20200909202454-errors) +- [Reflection](20200917155644-reflection) +- [Context](20200921154246-context) +- [Embedding](20200928193245-embedding) + +## Concurrency + +- [Goroutines](20200901141141-goroutines) + +### Sync + +- [Mutex](20200918173820-mutex) +- [WaitGroup](20200918174548-waitgroup) + +### Misc + +- When to use sync.Mutex or a channel[^1] + +## Libraries you should probably know about + +- http[^2] + +## Books & tutorials + +- Go by Example[^3] +- Learn Go with tests[^4] + +# Footnotes + +[^1]: + +[^2]: + +[^3]: + +[^4]: diff --git a/content/wiki/20200826142755-packages.md b/content/wiki/20200826142755-packages.md new file mode 100644 index 0000000..1da279f --- /dev/null +++ b/content/wiki/20200826142755-packages.md @@ -0,0 +1,66 @@ +--- +date: 2020-08-26 +id: 3123184d-c919-4cf6-8339-3f9b8ca5a1db +title: Golang Packages +--- + +# Basics + +Every Go program is made up of packages. Programs start running in +package \`main\`. + +By convention the pacckage name is the same as the last element of the +import path. For instance, the \`math/rand\` package comprises files +that begin with the statement \`package rand\`. + +``` go +package main + +import ( + "fmt" + "math/rand" +) + +func main() { + fmt.Println("My favorite number is", rand.Intn(10)) +} +``` + +# Imports + +It's best practice to convert multiple import statements to a "factored" +import statement: + +``` go +package main + +import "fmt" +import "math" + +func main() { + fmt.Printf("This uses multiple import statements\n") + fmt.Printf("Now you have %g problems.\n", math.Sqrt(7)) +} +``` + +should be + +``` go +package main + +import ( + "fmt" + "math" +) + +func main() { + fmt.Printf("This uses a parenthesized \"factored\" import statement\n") + fmt.Printf("Now you have %g problems.\n", math.Sqrt(7)) +} +``` + +# Exported names + +In Go, a name is exported if it begins with a capital letter. When +importing a package, you can refer only to its exported names. Any +"unexported" names are not accessible from outside the package. diff --git a/content/wiki/20200826151337-functions.md b/content/wiki/20200826151337-functions.md new file mode 100644 index 0000000..d5f4a69 --- /dev/null +++ b/content/wiki/20200826151337-functions.md @@ -0,0 +1,195 @@ +--- +date: 2020-08-26 +id: 009236f9-033d-44ef-8fa4-73cb05c3b390 +title: Golang Functions +--- + +# Arguments + +## Basics + +A function can take zero or more arguments. [Argument type comes after +the variable name](https://blog.golang.org/declaration-syntax). + +``` go +package main + +import "fmt" + +func add(x int, y int) int { + return x + y +} + +func main() { + fmt.Println(add(42, 13)) +} +``` + +When two or more consecutive named function parameters share a type, you +can omit the type from all but the last + +``` go +package main + +import "fmt" + +func add(x, y int) int { + return x + y +} + +func main() { + fmt.Println(add(42, 13)) +} +``` + +## Variadic + +Go also supports [variadic +functions](https://gobyexample.com/variadic-functions), ie functions +with any number of trailing arguments: + +``` go +package main + +import "fmt" + +func sum(nums ...int) { + fmt.Print(nums, " ") + total := 0 + for _, num := range nums { + total += num + } + fmt.Println(total) +} + +func main() { + + sum(1, 2) + sum(1, 2, 3) + + nums := []int{1, 2, 3, 4} + sum(nums...) +} +``` + +# Returns + +## Multiple results + +A function can return any number of results + +``` go +package main + +import "fmt" + +func swap(x, y string) (string, string) { + return y, x +} + +func main() { + a, b := swap("hello", "world") + fmt.Println(a, b) +} +``` + +## Named return values + +Go's return values may be named. If so, they are treated as variables +defined at the top of the function. These names shoudl be used to +document the meaning of the return values. A \`return\` statement +without arguments returns the named return values. This is known as a +"naked" return. Naked return statements should be used only short +functions as they can harm readability in longer functions. + +``` go +package main + +import "fmt" + +func split(sum int) (x, y int) { + x = sum * 4 / 9 + y = sum - x + return +} + +func main() { + fmt.Println(split(17)) +} +``` + +## Function values + +Like in [JavaScript](20200613170905-javascript) functions can be passed +around + +``` go +package main + +import ( + "fmt" + "math" +) + +func compute(fn func(float64, float64) float64) float64 { + return fn(3, 4) +} + +func main() { + hypot := func(x, y float64) float64 { + return math.Sqrt(x*x + y*y) + } + fmt.Println(hypot(5, 12)) + + fmt.Println(compute(hypot)) + fmt.Println(compute(math.Pow)) +} +``` + +## Function closures + +Like [JavaScript](20200613170905-javascript) function closures are +supported in Go as well + +``` go +package main + +import "fmt" + +func adder() func(int) int { + sum := 0 + return func(x int) int { + sum += x + return sum + } +} + +func main() { + pos, neg := adder(), adder() + for i := 0; i < 10; i++ { + fmt.Println( + pos(i), + neg(-2*i), + ) + } +} +``` + +# Implementing an Interface + +Here is an example of a function implementing an +[interface](20200831171822-interfaces): + +``` go +type BlindAlerter interface { + ScheduleAlertAt(duration time.Duration, amount int) +} + +// BlindAlerterFunc allows you to implement BlindAlerter with a function +type BlindAlerterFunc func(duration time.Duration, amount int) + +// ScheduleAlertAt is BlindAlerterFunc implementation of BlindAlerter +func (a BlindAlerterFunc) ScheduleAlertAt(duration time.Duration, amount int) { + a(duration, amount) +} +``` diff --git a/content/wiki/20200826151514-variables.md b/content/wiki/20200826151514-variables.md new file mode 100644 index 0000000..3f0d4f3 --- /dev/null +++ b/content/wiki/20200826151514-variables.md @@ -0,0 +1,232 @@ +--- +date: 2020-08-26 +id: ef9ed7f2-0bee-4405-a6d2-993cdea80029 +title: Golang variables +--- + +# Basics + +The \`var\` statement declares a list of variables. Type is last. A +\`var\` statement can be at package or function level. Use var when you +to set a variable type but don't want to set the variable value yet. + +``` go +package main + +import "fmt" + +var c, python, java bool + +func main() { + var i int + fmt.Println(i, c, python, java) +} +``` + +This also works with [interfaces](20200831171822-interfaces). + +``` go +package main + +import "fmt" + +type printSomething interface { + print() +} + +type agent struct { +} + +func (d *agent) print() { + fmt.Println("tralala") +} + +var ( + a = &agent{} +) + +func main() { + a.print() +} +``` + +# Initializers + +A var declaration can include initializers, one per variable. If an +initializer is present, the type can be omitted; the variable will take +the type of the initializer. + +``` go +package main + +import "fmt" + +var i, j int = 1, 2 + +func main() { + var c, python, java = true, false, "no!" + fmt.Println(i, j, c, python, java) +} +``` + +# Short variable declarations + +Inside a function, the := short assignment statement can be used in +place of a var declaration with implicit type. Outside a function, every +statement begins with a keyword (var, func, and so on) and so the := +construct is not available. + +``` go +package main + +import "fmt" + +func main() { + var i, j int = 1, 2 + k := 3 + c, python, java := true, false, "no!" + + fmt.Println(i, j, k, c, python, java) +} +``` + +# Basic types + +Go's basic types are + +bool + +string + +int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr + +byte // alias for uint8 + +rune // alias for int32 // represents a Unicode code point + +float32 float64 + +complex64 complex128 + +The example shows variables of several types, and also that variable +declarations may be "factored" into blocks, as with import statements. + +The int, uint, and uintptr types are usually 32 bits wide on 32-bit +systems and 64 bits wide on 64-bit systems. When you need an integer +value you should use int unless you have a specific reason to use a +sized or unsigned integer type. + +``` go +package main + +import ( + "fmt" + "math/cmplx" +) + +var ( + ToBe bool = false + MaxInt uint64 = 1<<64 - 1 + z complex128 = cmplx.Sqrt(-5 + 12i) +) + +func main() { + fmt.Printf("Type: %T Value: %v\n", ToBe, ToBe) + fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt) + fmt.Printf("Type: %T Value: %v\n", z, z) +} +``` + +# Zero values + +Variables declared without an explicit initial value are given their +zero value. + +The zero value is: + +- 0 for numeric types +- false for the boolean type +- "" for strings + +``` go +package main + +import "fmt" + +func main() { + var i int + var f float64 + var b bool + var s string + fmt.Printf("%v %v %v %q\n", i, f, b, s) +} +``` + +# Type conversions + +The expression \`T(v)\` converts the value v to the type T. + +``` go +package main + + import ( + "fmt" + "math" +) + +func main() { + var x, y int = 3, 4 + var f float64 = math.Sqrt(float64(x*x + y*y)) + var z uint = uint(f) + fmt.Println(x, y, z) +} +``` + +# Type inference + +When declaring a variable without specifying an explicit type (either by +using the := syntax or var = expression syntax), the variable's type is +inferred from the value on the right hand side. + +When the right hand side of the declaration is typed, the new variable +is of that same type: + +``` go +var i int +j := i // j is an int +``` + +But when the right hand side contains an untyped numeric constant, the +new variable may be an int, float64, or complex128 depending on the +precision of the constant: + +``` go +i := 42 // int +f := 3.142 // float64 +g := 0.867 + 0.5i // complex128 +``` + +# Constants + +Constants are declared like variables, but with the const keyword. + +Constants can be character, string, boolean, or numeric values. + +Constants cannot be declared using the := syntax. + +``` go +package main + +import "fmt" + +const Pi = 3.14 + +func main() { + const World = "世界" + fmt.Println("Hello", World) + fmt.Println("Happy", Pi, "Day") + + const Truth = true + fmt.Println("Go rules?", Truth) +} +``` diff --git a/content/wiki/20200826151846-flow_control_statements.md b/content/wiki/20200826151846-flow_control_statements.md new file mode 100644 index 0000000..3a21605 --- /dev/null +++ b/content/wiki/20200826151846-flow_control_statements.md @@ -0,0 +1,268 @@ +--- +date: 2020-08-26 +id: db553cc1-625c-4ddf-8d3c-cc0bba7b4345 +title: Golang flow control statements +--- + +# For + +Go has no \`while\`, \`do\` or \`until\` keywords for iteration, only +\`for\` + +``` go +package main + +import "fmt" + +func main() { + sum := 0 + for i := 0; i < 10; i++ { + sum += i + } + fmt.Println(sum) +} +``` + +Init and post statements are optional: + +``` go +package main + +import "fmt" + +func main() { + sum := 1 + for ; sum < 1000; { + sum += sum + } + fmt.Println(sum) +} +``` + +For is Go's "while": + +``` go +package main + +import "fmt" + +func main() { + sum := 1 + for sum < 1000 { + sum += sum + } + fmt.Println(sum) +} +``` + +Infinite loops are possible as well: + +``` go +package main + +func main() { + for { + } +} +``` + +Iterate over [Golang Arrays](20200828182327-arrays) & [Golang +slices](20200828182546-slices) with \`range\`: + +``` go +package main + +import ( + "fmt" +) + +func main() { + var numbers = []int{1,2,3,4,5} + var sum = 0 + + for _, number := range numbers { + sum += number + } + + fmt.Println("%s", sum) +} +``` + +# If + +Like for, the if statement can start with a short statement to execute +before the condition. + +Variables declared by the statement are only in scope until the end of +the if. + +``` go +package main + +import ( + "fmt" + "math" +) + +func pow(x, n, lim float64) float64 { + if v := math.Pow(x, n); v < lim { + return v + } + return lim +} + +func main() { + fmt.Println( + pow(3, 2, 10), + pow(3, 3, 20), + ) +} +``` + +Variables declared inside an if short statement are also available +inside any of the else blocks. + +``` go +package main + +import ( + "fmt" + "math" +) + +func pow(x, n, lim float64) float64 { + if v := math.Pow(x, n); v < lim { + return v + } else { + fmt.Printf("%g >= %g\n", v, lim) + } + // can't use v here, though + return lim +} + +func main() { + fmt.Println( + pow(3, 2, 10), + pow(3, 3, 20), + ) +} +``` + +# Switch + +Go's switch is like the one in C, C++, Java, JavaScript, and PHP, except +that Go only runs the selected case, not all the cases that follow. In +effect, the break statement that is needed at the end of each case in +those languages is provided automatically in Go. Another important +difference is that Go's switch cases need not be constants, and the +values involved need not be integers. + +``` go +package main + +import ( + "fmt" + "runtime" +) + +func main() { + fmt.Print("Go runs on ") + switch os := runtime.GOOS; os { + case "darwin": + fmt.Println("OS X.") + case "linux": + fmt.Println("Linux.") + default: + // freebsd, openbsd, + // plan9, windows... + fmt.Printf("%s.\n", os) + } +} +``` + +Switch without a condition is the same as switch true. This construct +can be a clean way to write long if-then-else chains. + +``` go +package main + +import ( + "fmt" + "time" +) + +func main() { + t := time.Now() + switch { + case t.Hour() < 12: + fmt.Println("Good morning!") + case t.Hour() < 17: + fmt.Println("Good afternoon.") + default: + fmt.Println("Good evening.") + } +} +``` + +Type switches are also a thing: + +``` go +package main + +import "fmt" + +func do(i interface{}) { + switch v := i.(type) { + case int: + fmt.Printf("Twice %v is %v\n", v, v*2) + case string: + fmt.Printf("%q is %v bytes long\n", v, len(v)) + default: + fmt.Printf("I don't know about type %T!\n", v) + } +} + +func main() { + do(21) + do("hello") + do(true) +} +``` + +# Defer + +A defer statement defers the execution of a function until the +surrounding function returns. The deferred call's arguments are +evaluated immediately, but the function call is not executed until the +surrounding function returns. + +``` go +package main + +import "fmt" + +func main() { + defer fmt.Println("world") + + fmt.Println("hello") +} +``` + +Deferred function calls are pushed onto a stack. When a function +returns, its deferred calls are executed in last-in-first-out order. + +``` go +package main + +import "fmt" + +func main() { + fmt.Println("counting") + + for i := 0; i < 10; i++ { + defer fmt.Println(i) + } + + fmt.Println("done") +} +``` diff --git a/content/wiki/20200826191127-tests.md b/content/wiki/20200826191127-tests.md new file mode 100644 index 0000000..4c61cc7 --- /dev/null +++ b/content/wiki/20200826191127-tests.md @@ -0,0 +1,205 @@ +--- +date: 2020-08-26 +id: d8edb970-fe2c-4774-b325-2f932b262ef5 +title: Tests in Golang +--- + +# Rules + +Test writing rules: + +- It needs to be in a file with a name like \`xxx~test~.go\` +- The test funciton must start with the word \`Test\` +- The test function takes one argument only \`t \*testing.T\` + +``` go +package main + +import "testing" + +func TestHello(t *testing.T) { + assertCorrectMessage := func(t *testing.T, got, want string) { + t.Helper() + if got != want { + t.Errorf("got %q want %q", got, want) + } + } + + t.Run("saying hello to people", func(t *testing.T) { + got := Hello("Chris", "") + want := "Hello, Chris" + assertCorrectMessage(t, got, want) + }) + + t.Run("empty string defaults to 'World'", func(t *testing.T) { + got := Hello("", "") + want := "Hello, World" + assertCorrectMessage(t, got, want) + }) + + t.Run("in Spanish", func(t *testing.T) { + got := Hello("Elodie", "Spanish") + want := "Hola, Elodie" + assertCorrectMessage(t, got, want) + }) + + t.Run("in French", func(t *testing.T) { + got := Hello("Jean Pierre", "French") + want := "Bonjour, Jean Pierre" + assertCorrectMessage(t, got, want) + }) + + t.Run("in Dutch", func(t *testing.T) { + got := Hello("Frans", "Dutch") + want := "Hoi, Frans" + assertCorrectMessage(t, got, want) + }) + +} +``` + +# Examples + +Examples can also be added to ~test~.go files. + +``` go +func ExampleAdd() { + sum := Add(1, 5) + fmt.Println(sum) + // Output: 6 +} +``` + +Example function will not be execute if the comment is removed + +# Benchmarking + +[Benchmarks](https://golang.org/pkg/testing/#hdr-Benchmarks) are a +first-class feature of Go, fantastic stuff! + +``` go +func BenchmarkRepeat(b *testing.B) { + for i := 0; i < b.N; i++ { + Repeat("a") + } +} +``` + +Following command runs benchmarks: + +``` shell +go test -bench=. +``` + +# Tools + +## Coverage + +[Coverage](https://blog.golang.org/cover) is built in as well: + +``` shell +go test -cover +``` + +## Race conditions + +In Go you can detect race conditions by adding the `-race` argument: + +``` shell +go test -race +``` + +# DeepEqual + +For \`slices\` & friends you can use \`reflect.DeepEqual\` to compare +variables in tests + +``` go +func TestSumAll(t *testing.T) { + + got := SumAll([]int{1, 2}, []int{0, 9}) + want := []int{3, 9} + + if !reflect.DeepEqual(got, want) { + t.Errorf("got %v want %v", got, want) + } +} +``` + +# TableDrivenTests + +Writing good tests is not trivial, but in many situations a lot of +ground can be covered with [table-driven +tests](https://github.com/golang/go/wiki/TableDrivenTests): Each table +entry is a complete test case with inputs and expected results, and +sometimes with additional information such as a test name to make the +test output easily readable. If you ever find yourself using copy and +paste when writing a test, think about whether refactoring into a +table-driven test or pulling the copied code out into a helper function +might be a better option. + +Given a table of test cases, the actual test simply iterates through all +table entries and for each entry performs the necessary tests. The test +code is written once and amortized over all table entries, so it makes +sense to write a careful test with good error messages. + +``` go +var flagtests = []struct { + in string + out string +}{ + {"%a", "[%a]"}, + {"%-a", "[%-a]"}, + {"%+a", "[%+a]"}, + {"%#a", "[%#a]"}, + {"% a", "[% a]"}, + {"%0a", "[%0a]"}, + {"%1.2a", "[%1.2a]"}, + {"%-1.2a", "[%-1.2a]"}, + {"%+1.2a", "[%+1.2a]"}, + {"%-+1.2a", "[%+-1.2a]"}, + {"%-+1.2abc", "[%+-1.2a]bc"}, + {"%-1.2abc", "[%-1.2a]bc"}, +} +func TestFlagParser(t *testing.T) { + var flagprinter flagPrinter + for _, tt := range flagtests { + t.Run(tt.in, func(t *testing.T) { + s := Sprintf(tt.in, &flagprinter) + if s != tt.out { + t.Errorf("got %q, want %q", s, tt.out) + } + }) + } +} +``` + +# Fatals + +Sometimes you want to throw fatal errors in tests to prevent problems, +for example in case \`nil\` is returned and you need to do stuff with +the return value in later tests: + +``` go +func assertError(t *testing.T, got error, want error) { + t.Helper() + if got == nil { + t.Fatal("didn't get an error but wanted one") + } + + if got != want { + t.Errorf("got %q, want %q", got, want) + } +} +``` + +# Handy packages + +- httptest[^1] +- quick[^2] + +# Footnotes + +[^1]: + +[^2]: diff --git a/content/wiki/20200826191508-tooling.md b/content/wiki/20200826191508-tooling.md new file mode 100644 index 0000000..ae5ff34 --- /dev/null +++ b/content/wiki/20200826191508-tooling.md @@ -0,0 +1,44 @@ +--- +date: 2020-08-26 +id: a8b17c59-bf17-4dc8-a0cd-5bf68b2e15c1 +title: Golang tooling +--- + +# Documentation + +Install godoc with `go get golang.org/x/tools/cmd/godoc` + +Documentation can be generated with + +``` shell +godoc --http :8000 +``` + +# Linters + +- [errcheck](https://github.com/kisielk/errcheck) + +# Testing + +## Code coverage + +``` shell +go test -cover +``` + +## Race conditions + +``` shell +go test -race +``` + +## Vetting + +Vet examines Go source code and reports suspicious constructs, such as +Printf calls whose arguments do not align with the format string. Vet +uses heuristics that do not guarantee all reports are genuine problems, +but it can find errors not caught by the compilers. + +``` shell +go vet +``` diff --git a/content/wiki/20200826201029-arrays.md b/content/wiki/20200826201029-arrays.md new file mode 100644 index 0000000..7b90ab5 --- /dev/null +++ b/content/wiki/20200826201029-arrays.md @@ -0,0 +1,29 @@ +--- +date: 2020-08-26 +id: e7ed8c3a-ee07-4d46-ace9-f354ee4a47b2 +title: JavaScript Arrays +--- + +- [Array Prototype + Methods](20201009090331-javascript_array_prototype_methods) +- [Array Functions](20201113103917-javascript_array_functions) +- [Destructuring Arrays](20201103111509-destructuring_arrays) + +# Syntax + +``` javascript +let listOfNumbers = [2, 3, 5, 7, 11]; +console.log(listOfNumbers[2]); // 5 +console.log(listOfNumbers[0]); // 2 +``` + +# Type + +In JavaScript arrays are a type of [object](20200826201605-objects) that +store sequences of things. `typeof` wil therefore return "object" + +``` javascript +let listOfThings = ["Car", "Mr Magoo", 42]; + +console.log(typeof listOfThings); // object +``` diff --git a/content/wiki/20200826201605-objects.md b/content/wiki/20200826201605-objects.md new file mode 100644 index 0000000..c5b64b9 --- /dev/null +++ b/content/wiki/20200826201605-objects.md @@ -0,0 +1,16 @@ +--- +date: 2020-08-26 +id: 18736297-fc4f-450c-be78-a13770d2c1c1 +title: JavaScript Objects +--- + +- [Object Properties](20201113091110-javascript_object_properties) +- [Prototypes](20201113091424-javascript_prototypes) +- [Object Prototype + Methods](20201113093204-javascript_object_prototype_methods) +- [Object Keywords](20201113093613-javascript_object_keywords) +- [Object Operators](20201113090050-javascript_object_operators) +- [Object Functions](20200826201959-object_functions) +- [Object Mutability](20200826201737-mutability) +- [Object Operators](20201113090050-javascript_object_operators) +- [Destructuring Objects](20201103111746-destructuring_objects) diff --git a/content/wiki/20200826201737-mutability.md b/content/wiki/20200826201737-mutability.md new file mode 100644 index 0000000..cacfd33 --- /dev/null +++ b/content/wiki/20200826201737-mutability.md @@ -0,0 +1,35 @@ +--- +date: 2020-08-26 +id: fd131977-33f2-42cd-9a3b-46ffd58b9e43 +title: JavaScript Object Mutability +--- + +# Description + +With objects, there is a difference between having two references to the +same object and having two different objects that contain the same +properties. + +# Examples + +``` javascript +let object1 = {value: 10}; +let object2 = object1; +let object3 = {value: 10}; + +console.log(object1 == object2); // true +console.log(object1 == object3); // false + +object1.value = 15; +console.log(object2.value); // 15 +console.log(object3.value); // 10 +``` + +\`const\` objects can have their values changed + +``` javascript +const score = { visitors: 0, home: 1 }; +score.visitors = 23; + +console.log(score); // { visitors: 23, home: 1 } +``` diff --git a/content/wiki/20200826201856-object_operators.md b/content/wiki/20200826201856-object_operators.md new file mode 100644 index 0000000..7b55fe7 --- /dev/null +++ b/content/wiki/20200826201856-object_operators.md @@ -0,0 +1,32 @@ +--- +date: 2020-08-26 +id: 7b46ba87-7328-479c-8d79-badb24ed7b19 +title: JavaScript object operators +--- + +# Delete operator + +The `delete` operator deletes a binding (duh) + +``` javascript +let anObject = {left: 1, right: 2}; +console.log(anObject.left); +delete anObject.left; +console.log(anObject.left); +console.log("left" in anObject); +console.log("right" in anObject); +``` + +# In operator + +The `in` operator tells you whether and object has a property with that +name + +``` javascript +let Object = { + thisPropertyExists: true +} + +console.log("thisPropertyExists" in Object) +console.log("thisPropertyDoesNotExist" in Object) +``` diff --git a/content/wiki/20200826201959-object_functions.md b/content/wiki/20200826201959-object_functions.md new file mode 100644 index 0000000..79b3d29 --- /dev/null +++ b/content/wiki/20200826201959-object_functions.md @@ -0,0 +1,19 @@ +--- +date: 2020-08-26 +id: 1d12fe9c-f655-49d2-8745-3148ec03cef9 +title: JavaScript Object Functions +--- + +- [Object.keys](20201113095226-object_keys) + +- [Object.assign](20201113095244-object_assign) + +- [Object.is](20201113095300-object_is) + +- [Object.entries](20201113102048-object_entries) + +- [Object.values](20201113102106-object_values) + +- [Object.getOwnPropertyDescriptors](20201113102125-object_getownpropertydescriptors) + +- [Object.fromEntries](20201116095124-object_fromentries) diff --git a/content/wiki/20200827142818-higher_order_functions.md b/content/wiki/20200827142818-higher_order_functions.md new file mode 100644 index 0000000..a29d4fc --- /dev/null +++ b/content/wiki/20200827142818-higher_order_functions.md @@ -0,0 +1,85 @@ +--- +date: 2020-08-27 +id: 513ff88e-d0c9-41d1-8416-57a4aff100c7 +title: JavaScript higher-order functions +--- + +# Examples + +Functions that operate on other functions, either by taking them as +arguments or by returning them, are called higher-order functions. They +allow us to abstract over actions as well as values. There are several +types, here are some examples. + +## Functions that create new functions + +``` javascript +function greaterThan(n) { + return m => m > n; +} +let greaterThan10 = greaterThan(10); +console.log(greaterThan10(11)); +``` + +## Functions that change other functions + +``` javascript +function noisy(f) { + return (...args) => { + console.log("calling with", args); + let result = f(...args); + console.log("called with", args, ", returned", result); + return result; + }; +} +noisy(Math.min)(3, 2, 1); +``` + +## Functions that provide new types of flow control + +``` javascript +function unless(test, then) { + if (!test) then(); +} + +repeat(3, n => { + unless(n % 2 == 1, () => { + console.log(n, "is even"); + }); +}); +``` + +## ES6 + +### Funciton properties + +1. name + + The `name` property contains the function's name: + + ``` javascript + function foo() {}; + console.log(foo.name); // foo + + let func1 = function () {}; + console.log(func1.name); // func1 + + let func4; + func4 = function () {}; + console.log(func4.name); // func4 + ``` + + 1. Default values + + ``` javascript + let [func1 = function () {}] = []; + console.log(func1.name); // func1 + + let { f2: func2 = function () {} } = {}; + console.log(func2.name); // func2 + + function g(func3 = function () {}) { + return func3.name; + } + console.log(g()); // func3 + ``` diff --git a/content/wiki/20200827170931-functions_macros.md b/content/wiki/20200827170931-functions_macros.md new file mode 100644 index 0000000..0196578 --- /dev/null +++ b/content/wiki/20200827170931-functions_macros.md @@ -0,0 +1,72 @@ +--- +date: 2020-08-27 +id: 1324afaa-085a-401c-9757-df93b6c51423 +title: Rust functions +--- + +# Functions + +## Case + +Rust uses [snake case](https://en.wikipedia.org/wiki/Snake_case) for +function and variable names. Functions always start with fn + +``` rust +fn main() { + println!("Hello, world!"); + + another_function(); +} + +fn another_function() { + println!("Another function."); +} +``` + +## Parameters + +In rust you **must** declare parameter types + +``` rust +fn main() { + another_function(5); +} + +fn another_function(x: i32) { + println!("The value of x is: {}", x); +} +``` + +## Rust is expressive + +Rust is an expressive language, so you have to do stuff like this: + +``` rust +fn main() { + let _x = 5; + + let y = { + let x = 3; + x + 1 + }; + + println!("The value of y is: {}", y); +} +``` + +## Return values + +Unless you add a return statement, most functions return the last +expression implicitly: + +``` rust +fn five() -> i32 { + 5 +} + +fn main() { + let x = five(); + + println!("The value of x is: {}", x); +} +``` diff --git a/content/wiki/20200827171036-tooling.md b/content/wiki/20200827171036-tooling.md new file mode 100644 index 0000000..6c765f2 --- /dev/null +++ b/content/wiki/20200827171036-tooling.md @@ -0,0 +1,66 @@ +--- +date: 2020-08-27 +id: 33187ecc-81fd-4136-ad10-b69e8463bd6d +title: Rust tooling +--- + +# Rustc + +Rustc handles Rust compilation `rustc main.rs` + +# Cargo + +Cargo is Rust's build system and package manager + +## Cargo commands + +### Create project + +``` shell +cargo new hello_cargo +``` + +### Build project + +``` shell +cargo build +``` + +### Build & run project + +``` shell +cargo run +``` + +1. Backtrace + + When you want to see an error backtrace set the `RUST_BACKTRACE` + environment variable: + + ``` shell + RUST_BACKTRACE=1 cargo run + ``` + +### Check code + +``` shell +cargo check +``` + +### Build for release + +``` shell +cargo build --release +``` + +## Cargo.toml + +``` toml +[package] +name = "hello_cargo" +version = "0.1.0" +authors = ["Your Name "] +edition = "2018" + +[dependencies] +``` diff --git a/content/wiki/20200827171318-rust_books.md b/content/wiki/20200827171318-rust_books.md new file mode 100644 index 0000000..4802ca3 --- /dev/null +++ b/content/wiki/20200827171318-rust_books.md @@ -0,0 +1,28 @@ +--- +date: 2020-08-27 +id: d1b696d7-2dfa-4b0c-b312-f3762b9ae020 +title: Rust books & exercises +--- + +# Books + +- The Rust Programming Language[^1] +- The Rust Performance Book[^2] +- Rust by example[^3] +- Rustonomicon[^4] + +# Exercises + +- Rustlings[^5] + +# Footnotes + +[^1]: + +[^2]: + +[^3]: + +[^4]: + +[^5]: diff --git a/content/wiki/20200827171554-variables_in_rust.md b/content/wiki/20200827171554-variables_in_rust.md new file mode 100644 index 0000000..f1a9f3c --- /dev/null +++ b/content/wiki/20200827171554-variables_in_rust.md @@ -0,0 +1,152 @@ +--- +date: 2020-08-27 +id: 9a604084-80a1-4868-be7b-950e7f43b65d +title: Rust variables +--- + +# Mutability + +By default variables in Rust are immutable. To make a variable mutable +one must explicity add \`mut\` in front of it + +``` rust +fn main() { + let mut x = 5; + println!("The value of x is: {}", x); + x = 6; + println!("The value of x is: {}", x); +} +``` + +# Constants + +Constatns are values that are bound to a name and are not allowed to +change. Some differences with variables: + +- You can't use \`mut\` with constants +- Constants are delared with \`const\` keyword instead of \`let\` +- Type value must be annotated +- Constants can be declared in any scope +- Constants may only be set to a constant expression, not the result + of a function call of any other value that could only be computed at + runtime + +``` rust +#![allow(unused_variables)] +fn main() { +const MAX_POINTS: u32 = 100_000; +} +``` + +# Shadowing + +You can declare a new variable with the same value as a previous +variable. The new variable "shadows" the previous variable + +``` rust +fn main() { + let x = 5; + + let x = x + 1; + + let x = x * 2; + + println!("The value of x is: {}", x); +} +``` + +Shadowing is different from marking a variable as mut, because we’ll get +a compile-time error if we accidentally try to reassign to this variable +without using the let keyword. By using let, we can perform a few +transformations on a value but have the variable be immutable after +those transformations have been completed. + +The other difference between mut and shadowing is that because we’re +effectively creating a new variable when we use the let keyword again, +we can change the type of the value but reuse the same name. For +example, say our program asks a user to show how many spaces they want +between some text by inputting space characters, but we really want to +store that input as a number: + +``` rust +fn main() { + let spaces = " "; + let spaces = spaces.len(); + + println!("There are {} spaces in the string", spaces) +} +``` + +# Data types + +## Tuple + +Tuple elements can be accessed directly by using a period. + +``` rust +fn main() { + let tup: (i32, f64, u8) = (500, 6.4, 1); + + println!("These are the tuple values {} {} {}", tup.0, tup.1, tup.2) +} +``` + +## Array + +In Rust every element of an array must have the same type. They also +have a fixed length, like tuples. + +``` rust +fn main() { + let _a = [1, 2, 3, 4, 5]; +} +``` + +You would write an array’s type by using square brackets, and within the +brackets include the type of each element, a semicolon, and then the +number of elements in the array, like so: + +``` rust +#![allow(unused_variables)] +fn main() { + let a: [i32; 5] = [1, 2, 3, 4, 5]; +} +``` + +You can also easily initialize an array that contains the same value for +each element: + +``` rust +#![allow(unused_variables)] +fn main() { + let a = [3; 5]; +} +``` + +Accessing array elements is also straightforward: + +``` rust +#![allow(unused_variables)] +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +## Destructuring + +Rust also supports destructuring + +``` rust +fn main() { + let tup = (500, 6.4, 1); + + let (x, y, z) = tup; + + println!("The value of x is: {}", x); + println!("The value of y is: {}", y); + println!("The value of z is: {}", z); +} +``` diff --git a/content/wiki/20200827190035-rust_comments.md b/content/wiki/20200827190035-rust_comments.md new file mode 100644 index 0000000..242ef53 --- /dev/null +++ b/content/wiki/20200827190035-rust_comments.md @@ -0,0 +1,114 @@ +--- +date: 2020-08-27 +id: f4c04f44-c7c3-4fa0-a4d6-e78995257b9c +title: Rust Comments +--- + +# Basics + +In Rust, the idiomatic comment style starts a comment with two slashes, +and the comment continues until the end of the line. For comments that +extend beyond a single line, you’ll need to include // on each line, +like this: + +``` rust +// So we’re doing something complicated here, long enough that we need +// multiple lines of comments to do it! Whew! Hopefully, this comment will +// explain what’s going on. +``` + +Comments can also be placed at the end of lines containing code: + +``` rust +fn main() { + println!("tralala") // This prints something +} +``` + +But if you're a sane person you'll comment above the code you're +annotating + +``` rust +// This prints something +fn main() { + println!("tralala") +} +``` + +# Documentation comments + +## */* + +This is like phpdoc, but for Rust. Documentation comments use three +slashes `///` and support Markdown notation: + +``` rust +/// Adds one to the number given. +/// +/// # Examples +/// +/// ``` +/// let arg = 5; +/// let answer = my_crate::add_one(arg); +/// +/// assert_eq!(6, answer); +/// ``` +pub fn add_one(x: i32) -> i32 { + x + 1 +} +``` + +Run `cargo doc` to generate HTML documentation from the comments. +`cargo doc --open` will open documentation in the browser. + +### Commonly used sections + +1. Panics + + The scenarios in which the function being documented could panic. + Callers of the function who don’t want their programs to panic + should make sure they don’t call the function in these situations. + +2. Errors + + If the function returns a `Result`, describing the kinds of errors + that might occur and what conditions might cause those errors to be + returned can be helpful to callers so they can write code to handle + the different kinds of errors in different ways. + +3. Safety + + If the function is `unsafe` to call, there should be a section + explaining why the function is unsafe and covering the invariants + that the function expects callers to uphold. + +## //! + +This is used for general comments: + +``` rust +//! # My Crate +//! +//! `my_crate` is a collection of utilities to make performing certain +//! calculations more convenient. + +/// Adds one to the number given. +// --snip-- +/// +/// # Examples +/// +/// ``` +/// let arg = 5; +/// let answer = my_crate::add_one(arg); +/// +/// assert_eq!(6, answer); +/// ``` +pub fn add_one(x: i32) -> i32 { + x + 1 +} +``` + +# Changes + +- [Linking To Items By Name](20201119170237-linking_to_items_by_name) +- [Search Aliases](20201119170710-search_aliases) diff --git a/content/wiki/20200827190443-rust_control_flow.md b/content/wiki/20200827190443-rust_control_flow.md new file mode 100644 index 0000000..1211ace --- /dev/null +++ b/content/wiki/20200827190443-rust_control_flow.md @@ -0,0 +1,97 @@ +--- +date: 2020-08-27 +id: 0ae97b2d-5a3c-40b5-9ce1-37aacb647c5d +title: Rust control flow +--- + +# Branching + +## If + +``` rust +fn main() { + let number = 3; + + if number < 5 { + println!("condition was true"); + } else { + println!("condition was false"); + } +} +``` + +Because Rust is expressive we can use an \`if\` expression on the right +side of a \`let\` statement: + +``` rust +fn main() { + let condition = true; + let number = if condition { 5 } else { 6 }; + + println!("The value of number is: {}", number); +} +``` + +# Loops + +## Loop + +This will loop forever + +``` rust +fn main() { + loop { + println!("again!"); + } +} +``` + +Loops can also return values: + +``` rust +fn main() { + let mut counter = 0; + + let result = loop { + counter += 1; + + if counter == 10 { + break counter * 2; + } + }; + + println!("The result is {}", result); +} +``` + +## While + +Rust also supports while loops: + +``` rust +fn main() { + let mut number = 3; + + while number != 0 { + println!("{}!", number); + + number -= 1; + } + + println!("LIFTOFF!!!"); +} +``` + +## For + +For loops are supported as well + +``` rust +fn main() { + let a = [10, 20, 30, 40, 50]; + + for element in a.iter() { + println!("the value is: {}", element); + } +} +``` diff --git a/content/wiki/20200828170945-ownership.md b/content/wiki/20200828170945-ownership.md new file mode 100644 index 0000000..a7150ce --- /dev/null +++ b/content/wiki/20200828170945-ownership.md @@ -0,0 +1,7 @@ +--- +date: 2020-08-28 +id: e51ace6b-e3ca-4e83-aa11-80848204bd68 +title: Ownership in Rust +--- + +TODO. Can't be bothered to write this now diff --git a/content/wiki/20200828180957-pointers.md b/content/wiki/20200828180957-pointers.md new file mode 100644 index 0000000..cb5e35b --- /dev/null +++ b/content/wiki/20200828180957-pointers.md @@ -0,0 +1,53 @@ +--- +date: 2020-08-28 +id: f2e19e3e-e28a-4998-8b0c-38ebfdb559e5 +title: Golang Pointers +--- + +# Basics + +Go also supports pointers. Default value is always NULL and you can't do +pointer arithmetic. Other than that, nothing that will blow your mind +here. + +``` go +package main + +import "fmt" + +func main() { + i, j := 42, 2701 + + p := &i // point to i + fmt.Println(*p) // read i through the pointer + *p = 21 // set i through the pointer + fmt.Println(i) // see the new value of i + + p = &j // point to j + *p = *p / 37 // divide j through the pointer + fmt.Println(j) // see the new value of j +} +``` + +# Pointers to [Golang Structs](20200828181259-structs) + +To facilitate lazy people like me Go allows you to lose the \`\*\` when +using a pointer to a struct + +``` go +package main + +import "fmt" + +type Vertex struct { + X int + Y int +} + +func main() { + v := Vertex{1, 2} + p := &v + p.X = 123 + fmt.Println(v) +} +``` diff --git a/content/wiki/20200828181259-structs.md b/content/wiki/20200828181259-structs.md new file mode 100644 index 0000000..a8ff1ba --- /dev/null +++ b/content/wiki/20200828181259-structs.md @@ -0,0 +1,186 @@ +--- +date: 2020-08-28 +id: 463ce364-f426-4089-a0ca-ffe45f0461f2 +title: Golang Structs +--- + +# Basics + +Golang structs are what you expect + +``` go +package main + +import "fmt" + +type Vertex struct { + X int + Y int +} + +func main() { + fmt.Println(Vertex{1, 2}) +} +``` + +# Struct fields + +Struct fields are accessed using a dot + +``` go +package main + +import "fmt" + +type Coorindate struct { + X int + Y int +} + +func main() { + coordinate := Coorindate{1, 67} + coordinate.X = 26 + fmt.Println(coordinate.X) +} +``` + +# Struct literals + +You can also newly allocate a struct by listing the values of its +fields. This is known as a "struct literal" (duh) + +``` go +package main + +import "fmt" + +type Vertex struct { + X, Y int +} + +var ( + v1 = Vertex{1, 2} // has type Vertex + v2 = Vertex{X: 1} // Y:0 is implicit + v3 = Vertex{} // X:0 and Y:0 + p = &Vertex{1, 2} // has type *Vertex +) + +func main() { + fmt.Println(v1, p, v2, v3) +} +``` + +# Struct tags + +[Struct tags](https://go.dev/wiki/Well-known-struct-tags) allow other +modules accessing struct members to format member values. + +## Control encoding + +``` go +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + "time" +) + +type User struct { + Name string `json:"name"` + Password string `json:"password"` + PreferredFish []string `json:"preferredFish"` + CreatedAt time.Time `json:"createdAt"` +} + +func main() { + u := &User{ + Name: "Sammy the Shark", + Password: "fisharegreat", + CreatedAt: time.Now(), + } + + out, err := json.MarshalIndent(u, "", " ") + if err != nil { + log.Println(err) + os.Exit(1) + } + + fmt.Println(string(out)) +} +``` + +## Remove empty fields + +``` go +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + "time" +) + +type User struct { + Name string `json:"name"` + Password string `json:"password"` + PreferredFish []string `json:"preferredFish,omitempty"` + CreatedAt time.Time `json:"createdAt"` +} + +func main() { + u := &User{ + Name: "Sammy the Shark", + Password: "fisharegreat", + CreatedAt: time.Now(), + } + + out, err := json.MarshalIndent(u, "", " ") + if err != nil { + log.Println(err) + os.Exit(1) + } + + fmt.Println(string(out)) +} +``` + +## Ignore private fields + +``` go +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + "time" +) + +type User struct { + Name string `json:"name"` + Password string `json:"-"` + CreatedAt time.Time `json:"createdAt"` +} + +func main() { + u := &User{ + Name: "Sammy the Shark", + Password: "fisharegreat", + CreatedAt: time.Now(), + } + + out, err := json.MarshalIndent(u, "", " ") + if err != nil { + log.Println(err) + os.Exit(1) + } + + fmt.Println(string(out)) +} +``` diff --git a/content/wiki/20200828182327-arrays.md b/content/wiki/20200828182327-arrays.md new file mode 100644 index 0000000..b76f7ef --- /dev/null +++ b/content/wiki/20200828182327-arrays.md @@ -0,0 +1,26 @@ +--- +date: 2020-08-28 +id: 24d46884-652c-4b64-b8e1-1baf81bea0f4 +title: Golang Arrays +--- + +Arrays are a thing in Go as well. Once initialized arrays cannot be +resized, if you're into **that** type of thing (no judgement) see +[slices](20200828182546-slices) + +``` go +package main + +import "fmt" + +func main() { + var a [2]string + a[0] = "Hello" + a[1] = "World" + fmt.Println(a[0], a[1]) + fmt.Println(a) + + primes := [6]int{2, 3, 5, 7, 11, 13} + fmt.Println(primes) +} +``` diff --git a/content/wiki/20200828182546-slices.md b/content/wiki/20200828182546-slices.md new file mode 100644 index 0000000..8b63d9c --- /dev/null +++ b/content/wiki/20200828182546-slices.md @@ -0,0 +1,290 @@ +--- +date: 2020-08-28 +id: 8b5fb822-d1ad-46de-9299-37e3d3f5108c +title: Golang slices +--- + +# Basics + +A slice is a dynamically sized, flexible view into the elements of an +array. Apparently they are much more common than arrays. Initialization +is pretty straight forward: + +``` go +package main + +import "fmt" + +func main() { + primes := [6]int{2, 3, 5, 7, 11, 13} + + var s []int = primes[1:4] + fmt.Println(s) +} +``` + +Slices are like references. Change something in the slice and the +[array](20200828182327-arrays) it references also changes + +``` go +package main + +import "fmt" + +func main() { + names := [4]string{ + "John", + "Paul", + "George", + "Ringo", + } + fmt.Println(names) + + a := names[0:2] + b := names[1:3] + fmt.Println(a, b) + + b[0] = "XXX" + fmt.Println(a, b) + fmt.Println(names) +} +``` + +Slices can contain any type, including other slices: + +``` go +package main + +import ( + "fmt" + "strings" +) + +func main() { + // Create a tic-tac-toe board. + board := [][]string{ + []string{"_", "_", "_"}, + []string{"_", "_", "_"}, + []string{"_", "_", "_"}, + } + + // The players take turns. + board[0][0] = "X" + board[2][2] = "O" + board[1][2] = "X" + board[1][0] = "O" + board[0][2] = "X" + + for i := 0; i < len(board); i++ { + fmt.Printf("%s\n", strings.Join(board[i], " ")) + } +} + +``` + +# Slice literals + +A slice literal is like an array, but without the length, so we add more +stuff to it later + +``` go +package main + +import "fmt" + +func main() { + q := []int{2, 3, 5, 7, 11, 13} + fmt.Println(q) + + r := []bool{true, false, true, true, false, true} + fmt.Println(r) + + s := []struct { + i int + b bool + }{ + {2, true}, + {3, false}, + {5, true}, + {7, true}, + {11, false}, + {13, true}, + } + fmt.Println(s) +} +``` + +# Slice defaults + +You can omit high and low bounds. As one would expect these default to 0 +and slice length respectively + +``` go +package main + +import "fmt" + +func main() { + s := []int{2, 3, 5, 7, 11, 13} + + s = s[1:4] + fmt.Println(s) + + s = s[:2] + fmt.Println(s) + + s = s[1:] + fmt.Println(s) +} +``` + +# Slice length and capacity + +One can lookup slice length (length of the slice) and capacity (length +of the array the slice references) + +``` go +package main + +import "fmt" + +func main() { + s := []int{2, 3, 5, 7, 11, 13} + printSlice(s) + + // Slice the slice to give it zero length. + s = s[:0] + printSlice(s) + + // Extend its length. + s = s[:4] + printSlice(s) + + // Drop its first two values. + s = s[2:] + printSlice(s) +} + +func printSlice(s []int) { + fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) +} +``` + +# Nil slices + +Empty slices are equal to `nil`. Maybe that's a good idea, maybe it +isn't. Typing this i'm too tired to give rational input to this +philosophical quagmire. + +``` go +package main + +import "fmt" + +func main() { + var s []int + fmt.Println(s, len(s), cap(s)) + if s == nil { + fmt.Println("nil!") + } +} +``` + +# Make + +Slices can be created with the `make` function, this way you can treat +them like arrays that we know and love. + +``` go +package main + +import "fmt" + +func main() { + a := make([]int, 5) + printSlice("a", a) + + b := make([]int, 0, 5) + printSlice("b", b) + + c := b[:2] + printSlice("c", c) + + d := c[2:5] + printSlice("d", d) +} + +func printSlice(s string, x []int) { + fmt.Printf("%s len=%d cap=%d %v\n", + s, len(x), cap(x), x) +} +``` + +# Append + +New elements can be added to a slice with the +[append](https://golang.org/pkg/builtin/#append) function + +``` go +package main + +import "fmt" + +func main() { + var s []int + printSlice(s) + + // append works on nil slices. + s = append(s, 0) + printSlice(s) + + // The slice grows as needed. + s = append(s, 1) + printSlice(s) + + // We can add more than one element at a time. + s = append(s, 2, 3, 4) + printSlice(s) +} + +func printSlice(s []int) { + fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) +} +``` + +# Range + +You can iterate over slices with `range` + +``` go +package main + +import "fmt" + +var pow = []int{1, 2, 4, 8, 16, 32, 64, 128} + +func main() { + for i, v := range pow { + fmt.Printf("2**%d = %d\n", i, v) + } +} +``` + +Index or value can be skipped by using `_`. In case you only want the +index, just omit the second variable entirely: + +``` go +package main + +import "fmt" + +func main() { + pow := make([]int, 10) + for i := range pow { + pow[i] = 1 << uint(i) // == 2**i + } + for _, value := range pow { + fmt.Printf("%d\n", value) + } +} +``` diff --git a/content/wiki/20200828192034-maps.md b/content/wiki/20200828192034-maps.md new file mode 100644 index 0000000..5ea16aa --- /dev/null +++ b/content/wiki/20200828192034-maps.md @@ -0,0 +1,126 @@ +--- +date: 2020-08-28 +id: 85fe90d9-f7d2-47fb-9471-f2557b1fa95d +title: Golang maps +--- + +# Basics + +A map maps keys to values, ie: associative arrays. Zero value of a map +is `nil`. `make` function returns a new `map`. + +``` go +package main + +import "fmt" + +type Vertex struct { + Lat, Long float64 +} + +var m map[string]Vertex + +func main() { + m = make(map[string]Vertex) + m["Bell Labs"] = Vertex{ + 40.68433, -74.39967, + } + fmt.Println(m["Bell Labs"]) +} +``` + +# Map literals + +These are essentially the same as [struct +literals](20200828181259-structs), keys are required. + +``` go +package main + +import "fmt" + +type Vertex struct { + Lat, Long float64 +} + +var m = map[string]Vertex{ + "Bell Labs": Vertex{ + 40.68433, -74.39967, + }, + "Google": Vertex{ + 37.42202, -122.08408, + }, +} + +func main() { + fmt.Println(m) +} +``` + +If top-level type is just a type name, it can be omitted from literal +elements. Saves some typing. + +``` go +package main + +import "fmt" + +type Vertex struct { + Lat, Long float64 +} + +var m = map[string]Vertex{ + "Bell Labs": {40.68433, -74.39967}, + "Google": {37.42202, -122.08408}, +} + +func main() { + fmt.Println(m) +} +``` + +# Mutating maps + +Nothing shocking here either. Map elements can be +added/deleted/modified/etc. + +``` go +package main + +import "fmt" + +func main() { + m := make(map[string]int) + + m["Answer"] = 42 + fmt.Println("The value:", m["Answer"]) + + m["Answer"] = 48 + fmt.Println("The value:", m["Answer"]) + + delete(m, "Answer") + fmt.Println("The value:", m["Answer"]) + + v, ok := m["Answer"] + fmt.Println("The value:", v, "Present?", ok) +} +``` + +# Types + +A `type` can be declared as a thin wrapper around a `map`: + +``` go +import "fmt" + +type Dictionary map[string]string + +func (d Dictionary) Search(word string) string { + return d[word] +} + +func main() { + d := Dictionary{"key": "This is the value"} + fmt.Println(d.Search("key")) +} +``` diff --git a/content/wiki/20200831155304-methods.md b/content/wiki/20200831155304-methods.md new file mode 100644 index 0000000..bbbd3ee --- /dev/null +++ b/content/wiki/20200831155304-methods.md @@ -0,0 +1,65 @@ +--- +date: 2020-08-31 +id: 03a6cd46-e6fb-46a8-96f7-16c37a6d140a +title: Golang methods +--- + +# Basics + +In Go methods can be defined on [struct](20200828181259-structs) and +non-struct types. In this case a **receiver** argument ias passed +between \`func\` keyword and the method name (\`Abs\`): + +``` go +package main + +import ( + "fmt" + "math" +) + +type Vertex struct { + X, Y float64 +} + +func (v Vertex) Abs() float64 { + return math.Sqrt(v.X*v.X + v.Y*v.Y) +} + +func main() { + v := Vertex{3, 4} + fmt.Println(v.Abs()) +} +``` + +# Pointers + +To modify struct values methods must be declared with pointer receivers: + +``` go +package main + +import ( + "fmt" + "math" +) + +type Vertex struct { + X, Y float64 +} + +func (v Vertex) Abs() float64 { + return math.Sqrt(v.X*v.X + v.Y*v.Y) +} + +func (v *Vertex) Scale(f float64) { + v.X = v.X * f + v.Y = v.Y * f +} + +func main() { + v := Vertex{3, 4} + v.Scale(10) + fmt.Println(v.Abs()) +} +``` diff --git a/content/wiki/20200831171822-interfaces.md b/content/wiki/20200831171822-interfaces.md new file mode 100644 index 0000000..3daea01 --- /dev/null +++ b/content/wiki/20200831171822-interfaces.md @@ -0,0 +1,179 @@ +--- +date: 2020-08-31 +id: 7ca10187-82d5-44fb-83a2-aa739c14cb24 +title: Golang interfaces +--- + +# Basics + +Go supports method interfaces: + +``` go +package main + +import ( + "fmt" + "math" +) + +type Abser interface { + Abs() float64 +} + +func main() { + var a Abser + f := MyFloat(-math.Sqrt2) + v := Vertex{3, 4} + + a = f // a MyFloat implements Abser + a = &v // a *Vertex implements Abser + + fmt.Println(a.Abs()) +} + +type MyFloat float64 + +func (f MyFloat) Abs() float64 { + if f < 0 { + return float64(-f) + } + return float64(f) +} + +type Vertex struct { + X, Y float64 +} + +func (v *Vertex) Abs() float64 { + return math.Sqrt(v.X*v.X + v.Y*v.Y) +} +``` + +Interfaces are implemented implicitly: + +``` go +package main + +import "fmt" + +type I interface { + M() +} + +type T struct { + S string +} + +// This method means type T implements the interface I, +// but we don't need to explicitly declare that it does so. +func (t T) M() { + fmt.Println(t.S) +} + +func main() { + var i I = T{"hello"} + i.M() +} +``` + +# Handy interfaces to know about + +## Stringer + +``` go +package main + +import "fmt" + +type Person struct { + Name string + Age int +} + +func (p Person) String() string { + return fmt.Sprintf("%v (%v years)", p.Name, p.Age) +} + +func main() { + a := Person{"Arthur Dent", 42} + z := Person{"Zaphod Beeblebrox", 9001} + fmt.Println(a, z) +} +``` + +## Error + +``` go +package main + +import ( + "fmt" + "time" +) + +type MyError struct { + When time.Time + What string +} + +func (e *MyError) Error() string { + return fmt.Sprintf("at %v, %s", + e.When, e.What) +} + +func run() error { + return &MyError{ + time.Now(), + "it didn't work", + } +} + +func main() { + if err := run(); err != nil { + fmt.Println(err) + } +} +``` + +## Reader + +``` go +package main + +import ( + "fmt" + "io" + "strings" +) + +func main() { + r := strings.NewReader("Hello, Reader!") + + b := make([]byte, 8) + for { + n, err := r.Read(b) + fmt.Printf("n = %v err = %v b = %v\n", n, err, b) + fmt.Printf("b[:n] = %q\n", b[:n]) + if err == io.EOF { + break + } + } +} +``` + +## Images + +``` go +package main + +import ( + "fmt" + "image" +) + +func main() { + m := image.NewRGBA(image.Rect(0, 0, 100, 100)) + fmt.Println(m.Bounds()) + fmt.Println(m.At(0, 0).RGBA()) +} +``` diff --git a/content/wiki/20200831193417-structs.md b/content/wiki/20200831193417-structs.md new file mode 100644 index 0000000..998dacb --- /dev/null +++ b/content/wiki/20200831193417-structs.md @@ -0,0 +1,155 @@ +--- +date: 2020-08-31 +id: 26048172-107d-4ad4-9906-acdf7935dfcb +title: Rust Structs Syntax +--- + +# Basics + +``` rust +struct User { + username: String, + email: String, + sign_in_count: u64, + active: bool, +} + +fn build_user(email: String, username: String) -> User { + // When struct field name and parameter name are the same shorthand syntax can be used + User { + email, + username, + active: true, + sign_in_count: 1, + } +} + +fn print_data(user: User) { + println!("User email is: {}", user.email); + println!("User username is: {}", user.username); + println!("User sign in count is: {}", user.sign_in_count); + println!("User active is: {}", user.active); +} + +fn main() { + let user1 = build_user( + String::from("someone@example.com"), + String::from("someusername123"), + ); + + println!("User 1"); + print_data(user1); + + let mut user2 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; + user2.email = String::from("anotheremail@example.com"); + + println!("User 2"); + print_data(user2); +} +``` + +``` rust + +``` + +# Tuple Struct + +``` rust +fn main() { + struct Color(i32, i32, i32); + struct Point(i32, i32, i32); + + let black = Color(0, 0, 0); + let origin = Point(0, 0, 0); +} +``` + +# Debug trait + +To print out debugging information we have the [debug +trait](https://doc.rust-lang.org/std/fmt/trait.Debug.html): + +``` rust +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +fn main() { + let rect1 = Rectangle { + width: 30, + height: 50, + }; + + println!("rect1 is {:?}", rect1); +} +``` + +# Methods + +Methods are like functions, but for structs: + +``` rust +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +impl Rectangle { + fn area(&self) -> u32 { + self.width * self.height + } +} + +fn main() { + let rect1 = Rectangle { + width: 30, + height: 50, + }; + + println!( + "The area of the rectangle is {} square pixels.", + rect1.area() + ); +} +``` + +# Associated Functions + +These are Rust's take on static functions. They **don't** take `self` as +a parameter + +``` rust +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +impl Rectangle { + fn area(&self) -> u32 { + self.width * self.height + } + fn square(size: u32) -> Rectangle { + Rectangle { + width: size, + height: size, + } + } +} + +fn main() { + let rect1 = Rectangle::square(10); + println!( + "The area of the rectangle is {} square pixels.", + rect1.area() + ); +} +``` diff --git a/content/wiki/20200901105237-error_handling.md b/content/wiki/20200901105237-error_handling.md new file mode 100644 index 0000000..699d78e --- /dev/null +++ b/content/wiki/20200901105237-error_handling.md @@ -0,0 +1,11 @@ +--- +date: 2020-09-01 +id: 57c3cee1-22dd-4a11-8a21-a19c571913e9 +title: JavaScript Error Handling +--- + +- [Exceptions](20201111092905-javascript_exceptions) +- [Error Sub Types](20201111093101-javascript_error_sub_types) +- [Strict Mode](20201111092510-javascript_strict_mode) +- [Custom Error Types](20201111093651-javascript_custom_error_types) +- [Finally](20201111094033-javascript_exceptions_finally) diff --git a/content/wiki/20200901141141-goroutines.md b/content/wiki/20200901141141-goroutines.md new file mode 100644 index 0000000..8a96978 --- /dev/null +++ b/content/wiki/20200901141141-goroutines.md @@ -0,0 +1,264 @@ +--- +date: 2020-09-01 +id: 56b6e0d5-090d-4859-9f06-c54a1a116515 +title: Goroutines +--- + +# Basics + +A `goroutine` is a lightweight thread managed by the Go runtime. + +``` go +package main + +import ( + "fmt" + "time" +) + +func say(s string) { + for i := 0; i < 5; i++ { + time.Sleep(100 * time.Millisecond) + fmt.Println(s) + } +} + +func main() { + go say("world") + say("hello") +} +``` + +# Channels + +Channels are a typed conduit through whichyou can send and receive +values with the channel operator \`\<-\`. By default, sends and receives +block until the other side is ready. This allows goroutines to +synchronize without explicit locks or condition variables. Channels +should generally be used for [passing ownership of +data](https://github.com/golang/go/wiki/MutexOrChannel). + +``` go +package main + +import "fmt" + +func sum(s []int, c chan int) { + sum := 0 + for _, v := range s { + sum += v + } + c <- sum // send sum to c +} + +func main() { + s := []int{7, 2, 8, -9, 4, 0} + + c := make(chan int) + go sum(s[:len(s)/2], c) + go sum(s[len(s)/2:], c) + x, y := <-c, <-c // receive from c + + fmt.Println(x, y, x+y) +} +``` + +Channels can also be **buffered**. Provide the buffer length as the +second argument to \`make\` to initialize a buffered channel: + +``` go +package main + +import "fmt" + +func main() { + ch := make(chan int, 2) + ch <- 1 + ch <- 2 + fmt.Println(<-ch) + fmt.Println(<-ch) +} +``` + +Sends to a buffered channel block only when the buffer is full. Receives +block when the buffer is empty. + +# Range and close + +A sender can close a channel to indicate that no more values will be +sent. Receivers can test whether a channel has been closed by assigning +a second parameter to the receive expression. + +Only the sender should close a channel, never the receiver. Sending on a +closed channel will cause a panic. Channels aren't like files; you don't +usually need to close them. Closing is only necessary when the receiver +must be told there are no more values coming, such as to terminate a +range loop. + +``` go +package main + +import ( + "fmt" +) + +func fibonacci(n int, c chan int) { + x, y := 0, 1 + for i := 0; i < n; i++ { + c <- x + x, y = y, x+y + } + close(c) +} + +func main() { + c := make(chan int, 10) + go fibonacci(cap(c), c) + for i := range c { + fmt.Println(i) + } +} +``` + +# Select + +The select statement lets a goroutine wait on multiple communication +operations. + +A select blocks until one of its cases can run, then it executes that +case. It chooses one at random if multiple are ready. + +``` go +package main + +import "fmt" + +func fibonacci(c, quit chan int) { + x, y := 0, 1 + for { + select { + case c <- x: + x, y = y, x+y + case <-quit: + fmt.Println("quit") + return + } + } +} + +func main() { + c := make(chan int) + quit := make(chan int) + go func() { + for i := 0; i < 10; i++ { + fmt.Println(<-c) + } + quit <- 0 + }() + fibonacci(c, quit) +} +``` + +\`default\` case in \`select\` is run if no other case is ready, as one +would expect + +``` go +package main + +import ( + "fmt" + "time" +) + +func main() { + tick := time.Tick(100 * time.Millisecond) + boom := time.After(500 * time.Millisecond) + for { + select { + case <-tick: + fmt.Println("tick.") + case <-boom: + fmt.Println("BOOM!") + return + default: + fmt.Println(" .") + time.Sleep(50 * time.Millisecond) + } + } +} +``` + +## Timeout + +Often you want to set a timeout value for `select` so it won't run +forver. [time.After](https://golang.org/pkg/time/#After) is a good way +of doing this: + +``` go +package main + +import ( + "fmt" + "time" +) + +var c chan int + +func handle(int) {} + +func main() { + select { + case m := <-c: + handle(m) + case <-time.After(10 * time.Second): + fmt.Println("timed out") + } +} +``` + +# sync.Mutex + +TO make sure only one goroutine at a time can access a variable we can +use \`sync.Mutex\` + +``` go +package main + +import ( + "fmt" + "sync" + "time" +) + +// SafeCounter is safe to use concurrently. +type SafeCounter struct { + mu sync.Mutex + v map[string]int +} + +// Inc increments the counter for the given key. +func (c *SafeCounter) Inc(key string) { + c.mu.Lock() + // Lock so only one goroutine at a time can access the map c.v. + c.v[key]++ + c.mu.Unlock() +} + +// Value returns the current value of the counter for the given key. +func (c *SafeCounter) Value(key string) int { + c.mu.Lock() + // Lock so only one goroutine at a time can access the map c.v. + defer c.mu.Unlock() + return c.v[key] +} + +func main() { + c := SafeCounter{v: make(map[string]int)} + for i := 0; i < 1000; i++ { + go c.Inc("somekey") + } + + time.Sleep(time.Second) + fmt.Println(c.Value("somekey")) +} +``` diff --git a/content/wiki/20200902150714-enums.md b/content/wiki/20200902150714-enums.md new file mode 100644 index 0000000..7b32263 --- /dev/null +++ b/content/wiki/20200902150714-enums.md @@ -0,0 +1,263 @@ +--- +date: 2020-09-02 +id: b95f09af-2cd0-46f2-872e-3cb542d2b2e9 +title: Rust enums +--- + +# Basics + +Rust also supports +[enums](https://doc.rust-lang.org/rust-by-example/custom_types/enum.html). + +``` rust +use std::fmt::Debug; + +#[derive(Debug)] +enum Message { + Write(String), +} + +fn main() { + let m = Message::Write(String::from("Hello!")); + println!("{:?}", m) +} +``` + +# Methods + +As with [structs](20200831193417-structs), methods can be defined as +well: + +``` rust +use std::fmt::Debug; + +#[derive(Debug)] +enum Message { + Write(String), +} + +impl Message { + fn call(&self) { + println!("tralala"); + println!("{:?}", self) + } +} + +fn main() { + let m = Message::Write(String::from("Hello!")); + m.call(); +} +``` + +# Standard library enums + +## Option + +Instead of \`null\` Rust has the +[Option](https://doc.rust-lang.org/std/option/enum.Option.html) enum +built in: + +``` rust +fn main() { + let some_number = Some(5); + let some_string = Some("a string"); + + let absent_number: Option = None; +} +``` + +The cool thing about using Option is that \`Option\\` and \`T\` are +different types, therefore the programmer has to define if NULL is +acceptable beforehand. The following won't run: + +``` rust +fn main() { + let x: i8 = 5; + let y: Option = Some(5); + + let sum = x + y; +} +``` + +Huzzah, No more having to worry about incorrectly assuming a not null +value! + +# Match control flow operator + +Think of \`switch\`, but for enums. + +``` rust +enum Coin { + Penny, + Nickel, + Dime, + Quarter, +} + +fn value_in_cents(coin: Coin) -> u8 { + match coin { + Coin::Penny => { + println!("Lucky penny!"); + 1 + } + Coin::Nickel => 5, + Coin::Dime => 10, + Coin::Quarter => 25, + } +} + +fn main() {} +``` + +## Patterns that bind to values + +Another useful feature of match arms is that they can bind to the parts +of the values that match the pattern. This is how we can extract values +out of enum variants. + +``` rust +#[derive(Debug)] +enum UsState { + Alabama, + Alaska, + // --snip-- +} + +enum Coin { + Penny, + Nickel, + Dime, + Quarter(UsState), +} + +fn value_in_cents(coin: Coin) -> u8 { + match coin { + Coin::Penny => 1, + Coin::Nickel => 5, + Coin::Dime => 10, + Coin::Quarter(state) => { + println!("State quarter from {:?}!", state); + 25 + } + } +} + +fn main() { + value_in_cents(Coin::Quarter(UsState::Alaska)); +} +``` + +## Matching with Option\ + +\`match\` also plays nice with \`Option\\`: + +``` rust +fn main() { + fn plus_one(x: Option) -> Option { + match x { + None => None, + Some(i) => Some(i + 1), + } + } + + let five = Some(5); + let six = plus_one(five); + let none = plus_one(None); +} +``` + +## The \_ Placeholder + +Rust also has a pattern we can use when we don’t want to list all +possible values: + +``` rust +fn main() { + let some_u8_value = 0u8; + match some_u8_value { + 1 => println!("one"), + 3 => println!("three"), + 5 => println!("five"), + 7 => println!("seven"), + _ => (), + } +} +``` + +## if let syntax suger + +``` rust +fn main() { + let some_u8_value = Some(0u8); + match some_u8_value { + Some(3) => println!("three"), + _ => (), + } +} +``` + +is the same as + +``` rust +fn main() { + let some_u8_value = Some(0u8); + if let Some(3) = some_u8_value { + println!("three"); + } +} +``` + +and + +``` rust +#[derive(Debug)] +enum UsState { + Alabama, + Alaska, + // --snip-- +} + +enum Coin { + Penny, + Nickel, + Dime, + Quarter(UsState), +} + +fn main() { + let coin = Coin::Penny; + let mut count = 0; + match coin { + Coin::Quarter(state) => println!("State quarter from {:?}!", state), + _ => count += 1, + } +} +``` + +is the same as + +``` rust +#[derive(Debug)] +enum UsState { + Alabama, + Alaska, + // --snip-- +} + +enum Coin { + Penny, + Nickel, + Dime, + Quarter(UsState), +} + +fn main() { + let coin = Coin::Penny; + let mut count = 0; + if let Coin::Quarter(state) = coin { + println!("State quarter from {:?}!", state); + } else { + count += 1; + } +} +``` diff --git a/content/wiki/20200902162305-regular_expressions.md b/content/wiki/20200902162305-regular_expressions.md new file mode 100644 index 0000000..185c2d1 --- /dev/null +++ b/content/wiki/20200902162305-regular_expressions.md @@ -0,0 +1,38 @@ +--- +date: 2020-09-02 +id: 9f63288d-8d70-4b20-a853-66c8f75418c0 +title: JavaScript Regular Expressions +--- + +# Prototype Methods + +- [test](20201104101723-javascript_regexp_test_method) +- [exec](20201104101924-javascript_regexp_exec_method) +- [match](20201104102212-javascript_regexp_match_method) +- [matchAll](20201116165324-matchall_expression) +- [replace](20201104102343-javascript_regexp_replace_method) +- [search](20201104102506-javascript_regexp_search_method) + +# Groups + +- [JavaScript RegExp Numbered Capture + Groups](20201104095851-javascript_regexp_numbered_capture_groups) +- [JavaScript RegExp Named Capture + Groups](20201104100431-javascript_regexp_named_capture_groups) + +# Escapes + +- [JavaScript RegExp Unicode Property + Escapes](20201106090634-javascript_regexp_unicode_property_escapes) + +# Assertions + +- [Lookahead + Assertions](20201109132457-javascript_lookahead_assertions) +- [Lookbehind + Assertions](20201109132944-javascript_lookbehind_assertions) + +# Flags + +- [JavaScript RegExp /s flag](20201110094807-javascript_regexp_s_flag) +- [JavaScript RegExp /u flag](20201110095139-javascript_regexp_u_flag) diff --git a/content/wiki/20200909202454-errors.md b/content/wiki/20200909202454-errors.md new file mode 100644 index 0000000..352fc57 --- /dev/null +++ b/content/wiki/20200909202454-errors.md @@ -0,0 +1,57 @@ +--- +date: 2020-09-09 +id: 5114b51a-da22-4c9c-a12c-c416aeb984b6 +title: Golang Errors +--- + +# Basics + +Go supports Errors + +``` go + +import ( + "errors" + "fmt" +) + +func ThrowError(throwError bool) error { + if throwError { + return errors.New("This is an error") + } + + fmt.Println("No error was thrown!") + return nil +} + +func main() { + ThrowError(true) + ThrowError(false) +} +``` + +# Wrappers + +It appears to be good practice to make errors a `const`. This example +uses the Error [interface](20200831171822-interfaces): + +``` go +const ( + ErrNotFound = DictionaryErr("could not find the word you were looking for") + ErrWordExists = DictionaryErr("cannot add word because it already exists") +) + +type DictionaryErr string + +func (e DictionaryErr) Error() string { + return string(e) +} +``` + +# Handy Links + +- Constant errors[^1] + +# Footnotes + +[^1]: diff --git a/content/wiki/20200911150451-callbacks.md b/content/wiki/20200911150451-callbacks.md new file mode 100644 index 0000000..cc4b435 --- /dev/null +++ b/content/wiki/20200911150451-callbacks.md @@ -0,0 +1,27 @@ +--- +date: 2020-09-11 +id: 6b091d50-aa10-4ba8-a652-43cd5433371e +title: JavaScript Callbacks +--- + +# Examples + +## setTimeout + +``` javascript +setTimeout(() => { console.log("This will echo after 2 seconds!"); }, 2000); +``` + +# ES6 + +## Best practices + +### Prefer arrow functions as callbacks + +As callbacks, [arrow functions](20201006111349-arrow_functions) have two +advantages over traditional functions: + +- `this` is lexical and therefore safer to use. +- Their syntax is more compact. That matters especially in functional + programming, where there are many higher-order functions and methods + (functions and methods whose parameters are functions). diff --git a/content/wiki/20200911154351-promises.md b/content/wiki/20200911154351-promises.md new file mode 100644 index 0000000..88e5250 --- /dev/null +++ b/content/wiki/20200911154351-promises.md @@ -0,0 +1,39 @@ +--- +date: 2020-09-11 +id: 14e0ce4b-b4b1-46fe-946a-c519550682ac +title: JavaScript Promises +--- + +# Introduction + +A Promise[^1] is an asynchronous action that may complete at some point +and produce a value. It is able to notify anyone who is interested when +its value is available. + +``` javascript +let fifteen = Promise.resolve(15); +fifteen.then(value => console.log(`Got ${value}`)) +``` + +# Parallel + +- [Executing Promises in Parallel + (Promises.all)](20201111094957-executing_promises_in_parallel_promises_all) +- [Promise.allSettled](20201116163327-promise_allsettled) + +# Errors + +- [Catching Promise Errors](20201111095100-catching_promise_errors) +- [Finally](20201111095454-javascript_promises_finally) + +# Producing & Consuming + +Use [Async functions](20201026103714-javascript_async_functions) instead +of this. + +- [Producing Promises](20201111095230-producing_promises) +- [Consuming Promises](20201111095316-javascript_consuming_promises) + +# Footnotes + +[^1]: diff --git a/content/wiki/20200911155947-generators.md b/content/wiki/20200911155947-generators.md new file mode 100644 index 0000000..8fd01ac --- /dev/null +++ b/content/wiki/20200911155947-generators.md @@ -0,0 +1,123 @@ +--- +date: 2020-09-11 +id: b2b11ef2-898f-45c7-ad25-967ac7bc9d8b +title: JavaScript Generators +--- + +# ES6 + +## Introduction + +Generators are processes that you can pause and resume. Generators are +defined with `function*`. + +``` javascript +const foo = function* () { + yield 'a'; + yield 'b'; + yield 'c'; +}; + +let str = ''; +for (const val of foo()) { + str = str + val; +} + +console.log(str); +``` + +## Generator Kinds + +### Generator function declarations + +``` javascript +function* genFunc() { } +const genObj = genFunc(); +``` + +### Generator function expressions + +``` javascript +const genFunc = function* () { }; +const genObj = genFunc(); +``` + +### Generator method definitions in object literals + +``` javascript +const obj = { + * generatorMethod() { + } +}; +const genObj = obj.generatorMethod(); +``` + +### Generator method definitions in class definitions + +``` javascript +class MyClass { + * generatorMethod() { + } +} +const myInst = new MyClass(); +const genObj = myInst.generatorMethod(); +``` + +# Examples + +## Iterables + +``` javascript +function* objectEntries(obj) { + const propKeys = Reflect.ownKeys(obj); + + for (const propKey of propKeys) { + // `yield` returns a value and then pauses + // the generator. Later, execution continues + // where it was previously paused. + yield [propKey, obj[propKey]]; + } +} + +const jane = { first: 'Jane', last: 'Doe' }; +for (const [key,value] of objectEntries(jane)) { + console.log(`${key}: ${value}`); +} + +// Output: +// first: Jane +// last: Doe +``` + +## Async Iterables + +``` javascript +async function* createAsyncIterable(syncIterable) { + for (const elem of syncIterable) { + yield elem; + } +} +``` + +## Asynchronous code + +``` javascript +const fetchJson = co.wrap(function* (url) { + try { + let request = yield fetch(url); + let text = yield request.text(); + return JSON.parse(text); + } + catch (error) { + console.log(`ERROR: ${error.stack}`); + } +}); + +fetchJson('http://example.com/some_file.json') +.then(obj => console.log(obj)); +``` + +# Also see + +- [Iterables](20201014092625-javascript_iterables) +- [Promises](20200911154351-promises) diff --git a/content/wiki/20200915140449-vectors.md b/content/wiki/20200915140449-vectors.md new file mode 100644 index 0000000..97f9cda --- /dev/null +++ b/content/wiki/20200915140449-vectors.md @@ -0,0 +1,148 @@ +--- +date: 2020-09-15 +id: 2eec2c96-e006-4a53-b5cc-fd39f466a6b7 +title: Rust Vectors +--- + +# Traits + +## std + +### convert + +- [TryInto](20201119171245-tryinto) + +# Description + +Vectors allow you to store more than one value in a single data +structure that puts all the values next to each other in memory. Vectors +can only store values of the same type. They are useful when you have a +list of items, such as the lines of text in a file or the prices of +items in a shopping cart. + +# Creating a New Vector + +``` rust +fn main() { + let v: Vec = Vec::new(); +} +``` + +## vec! macro + +Rust can often infer the type of value you want to store in the Vector. +For convenience one can also use the [vec! +macro](https://doc.rust-lang.org/std/macro.vec.html). + +``` rust +fn main() { + let v = vec![1, 2, 3]; +} +``` + +# Updating a Vector + +``` rust +fn main() { + let mut v = Vec::new(); + + v.push(5); + v.push(6); + v.push(7); + v.push(8); +} +``` + +# Dropping a Vector + +Like other [structs](20200831193417-structs), vectors are freed when +they go out of scope, along with the vector contents: + +``` rust +fn main() { + { + let v = vec![1, 2, 3, 4]; + + // do stuff with v + } // <- v goes out of scope and is freed here +} +``` + +# Read Vector elements + +There are two ways to reference a value stored in a vector: + +``` rust +fn main() { + let v = vec![1, 2, 3, 4, 5]; + + let third: &i32 = &v[2]; + println!("The third element is {}", third); + + match v.get(2) { + Some(third) => println!("The third element is {}", third), + None => println!("There is no third element."), + } +} +``` + +Using +[get](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.get) +together with +[match](https://doc.rust-lang.org/rust-by-example/flow_control/match.html) +seems preferable, as trying to get non existant elements with method \#1 +will cause an \`index out of bounds\` panic: + +``` rust +fn main() { + let v = vec![1, 2, 3, 4, 5]; + + let does_not_exist = &v[100]; + let does_not_exist = v.get(100); +} +``` + +When the `get` method is passed an index that is outside the vector, it +returns `None` without panicking. + +# Iteration + +## Immutable references + +``` rust +fn main() { + let v = vec![100, 32, 57]; + for i in &v { + println!("{}", i); + } +} +``` + +## Mutable references + +``` rust +fn main() { + let mut v = vec![100, 32, 57]; + for i in &mut v { + *i += 50; + } +} +``` + +# Using Enums to store multiple types + +``` rust +fn main() { + enum SpreadsheetCell { + Int(i32), + Float(f64), + Text(String), + } + + let row = vec![ + SpreadsheetCell::Int(3), + SpreadsheetCell::Text(String::from("blue")), + SpreadsheetCell::Float(10.12), + ]; +} +``` diff --git a/content/wiki/20200915151358-strings.md b/content/wiki/20200915151358-strings.md new file mode 100644 index 0000000..4bcc45d --- /dev/null +++ b/content/wiki/20200915151358-strings.md @@ -0,0 +1,145 @@ +--- +date: 2020-09-15 +id: 490f0710-971d-4150-a339-4a8c2f5d19a8 +title: Rust Strings +--- + +# Description + +The `String` type, which is provided by Rust’s standard library rather +than coded into the core language, is a growable, mutable, owned, UTF-8 +encoded string type. When Rustaceans refer to “strings” in Rust, they +usually mean the `String` and the string slice `&str` types, not just +one of those types. Although this section is largely about `String`, +both types are used heavily in Rust’s standard library, and both +`String` and string slices are UTF-8 encoded. + +# Creating a New String + +Many [Vector operations](20200915140449-vectors) are also available for +Strings. + +``` rust +fn main() { + let mut s = String::new(); +} +``` + +## to~string~ + +To generate a `String` with initial data we can use the +[to~string~](https://doc.rust-lang.org/std/string/trait.ToString.html#tymethod.to_string) +method: + +``` rust +fn main() { + let data = "initial contents"; + + let s = data.to_string(); + + // the method also works on a literal directly: + let s = "initial contents".to_string(); +} +``` + +## String::from + +The same can be accomplished with `String::from`: + +``` rust +fn main() { + let s = String::from("initial contents"); +} +``` + +# Updating a String + +## push~str~ + +``` rust +fn main() { + let mut s = String::from("foo"); + s.push_str("bar"); + + println!("s is {}", s) +} +``` + +## push + +`push` adds a single character to a string: + +``` rust +fn main() { + let mut s = String::from("lo"); + s.push('l'); + + println!("s is {}", s) +} +``` + +# Concatentation + +``` rust +fn main() { + let s1 = String::from("Hello, "); + let s2 = String::from("world!"); + let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used + + println!("s3 is {}", s3) +} +``` + +## Concatenate multiple strings + +### With + + +``` rust +fn main() { + let s1 = String::from("tic"); + let s2 = String::from("tac"); + let s3 = String::from("toe"); + + let s = s1 + "-" + &s2 + "-" + &s3; + + println!("s is {}", s) +} +``` + +### With format! + +``` rust +fn main() { + let s1 = String::from("tic"); + let s2 = String::from("tac"); + let s3 = String::from("toe"); + + let s = format!("{}-{}-{}", s1, s2, s3); + + println!("s is {}", s) +} +``` + +# Iteration + +## Chars + +``` rust +#![allow(unused)] +fn main() { + for c in "नमस्ते".chars() { + println!("{}", c); + } +} +``` + +## Bytes + +``` rust +#![allow(unused)] +fn main() { + for b in "नमस्ते".bytes() { + println!("{}", b); + } +} +``` diff --git a/content/wiki/20200915153033-hash_maps.md b/content/wiki/20200915153033-hash_maps.md new file mode 100644 index 0000000..be77839 --- /dev/null +++ b/content/wiki/20200915153033-hash_maps.md @@ -0,0 +1,137 @@ +--- +date: 2020-09-15 +id: 2b38c21d-4971-42fb-9b87-5d68468e95e0 +title: Rust Hash Maps +--- + +# Description + +The type `HashMap` stores a mapping of keys of type `K` to values +of type `V`. It does this via a hashing function, which determines how +it places these keys and values into memory. Many programming languages +support this kind of data structure, but they often use a different +name, such as hash, map, object, hash table, dictionary, or associative +array, just to name a few. + +## Creating a New Hash Maps + +``` rust +fn main() { + use std::collections::HashMap; + + let mut scores = HashMap::new(); + + scores.insert(String::from("Blue"), 10); + scores.insert(String::from("Yellow"), 50); + + println!("{}", scores["Blue"]) +} +``` + +### collect + +Another way of constructing a hash map is by using iterators and the +[collect](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect) +method on a vector of tuples, where each tuple consists of a key and its +value. + +``` rust +fn main() { + use std::collections::HashMap; + + let teams = vec![String::from("Blue"), String::from("Yellow")]; + let initial_scores = vec![10, 50]; + + let scores: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect(); + + println!("{}", scores["Blue"]) +} +``` + +## Ownership + +For types that implement the `Copy` trait, like `i32`, the values are +copied into the hash map. For owned values like `String`, the values +will be moved and the hash map will be the owner of those values: + +``` rust +fn main() { + use std::collections::HashMap; + + let field_name = String::from("Favorite color"); + let field_value = String::from("Blue"); + + let mut map = HashMap::new(); + map.insert(field_name, field_value); + // field_name and field_value are invalid at this point +} +``` + +## Accessing values + +``` rust +fn main() { + use std::collections::HashMap; + + let mut scores = HashMap::new(); + + scores.insert(String::from("Blue"), 10); + scores.insert(String::from("Yellow"), 50); + + for (key, value) in &scores { + println!("{}: {}", key, value); + } +} +``` + +## Updating + +### Overwriting a Value + +``` rust +fn main() { + use std::collections::HashMap; + + let mut scores = HashMap::new(); + + scores.insert(String::from("Blue"), 10); + scores.insert(String::from("Blue"), 25); + + println!("{:?}", scores); +} +``` + +### Inserting a value only if the Key has no value + +``` rust +fn main() { + use std::collections::HashMap; + + let mut scores = HashMap::new(); + scores.insert(String::from("Blue"), 10); + + scores.entry(String::from("Yellow")).or_insert(50); + scores.entry(String::from("Blue")).or_insert(50); + + println!("{:?}", scores); +} +``` + +### Updating a value based on the old value + +``` rust +fn main() { + use std::collections::HashMap; + + let text = "hello world wonderful world"; + + let mut map = HashMap::new(); + + for word in text.split_whitespace() { + let count = map.entry(word).or_insert(0); + *count += 1; + } + + println!("{:?}", map); +} +``` diff --git a/content/wiki/20200916162727-unrecoverable_errors.md b/content/wiki/20200916162727-unrecoverable_errors.md new file mode 100644 index 0000000..09c7c35 --- /dev/null +++ b/content/wiki/20200916162727-unrecoverable_errors.md @@ -0,0 +1,34 @@ +--- +date: 2020-09-16 +id: 2a1d0b2f-9f23-4872-a83f-aa01a84756b5 +title: Rust Unrecoverable Errors +--- + +# Unwinding vs Aborting + +By default, when a panic occurs, the program starts *unwinding*, which +means Rust walks back up the stack and cleans up the data from each +function it encounters. But this walking back and cleanup is a lot of +work. The alternative is to immediately abort, which ends the program +without cleaning up. Memory that the program was using will then need to +be cleaned up by the operating system. If in your project you need to +make the resulting binary as small as possible, you can switch from +unwinding to aborting upon a panic by adding `panic = 'abort'` to the +appropriate `[profile]` sections in your *Cargo.toml* file. For example, +if you want to abort on panic in release mode, add this: + +``` toml +[profile.release] +panic = 'abort' +``` + +# panic! + +When doodie hits the fan and there's no way out, use the +[panic!](https://doc.rust-lang.org/std/macro.panic.html) macro: + +``` rust +fn main() { + panic!("crash and burn"); +} +``` diff --git a/content/wiki/20200916163737-recoverable_errors.md b/content/wiki/20200916163737-recoverable_errors.md new file mode 100644 index 0000000..9f4c5e8 --- /dev/null +++ b/content/wiki/20200916163737-recoverable_errors.md @@ -0,0 +1,171 @@ +--- +date: 2020-09-16 +id: cbdaa6b4-cf72-45fb-ac16-79afd8900478 +title: Rust Recoverable Errors +--- + +# match + +In Rust we use the [match](20201006102934-pattern_syntax) expression to +check for errors in the +[Result](https://doc.rust-lang.org/std/result/enum.Result.html): + +``` rust +use std::fs::File; + +fn main() { + let f = File::open("hello.txt"); + + let f = match f { + Ok(file) => file, + Err(error) => panic!("Problem opening the file: {:?}", error), + }; +} +``` + +Generally speaking you want to perform different actions depending on +the error type: + +``` rust +use std::fs::File; +use std::io::ErrorKind; + +fn main() { + let f = File::open("hello.txt"); + + let f = match f { + Ok(file) => file, + Err(error) => match error.kind() { + ErrorKind::NotFound => match File::create("hello.txt") { + Ok(fc) => fc, + Err(e) => panic!("Problem creating the file: {:?}", e), + }, + other_error => panic!("Problem opening the file: {:?}", other_error), + }, + }; +} +``` + +## Ditching match altogether + +A more elegant way of writing the above: + +``` rust +use std::fs::File; +use std::io::ErrorKind; + +fn main() { + let f = File::open("hello.txt").unwrap_or_else(|error| { + if error.kind() == ErrorKind::NotFound { + File::create("hello.txt").unwrap_or_else(|error| { + panic!("Problem creating the file: {:?}", error); + }) + } else { + panic!("Problem opening the file: {:?}", error); + } + }); +} +``` + +# Panic on Error shortcuts + +## unwrap + +If the `Result` value is `Ok`, +[unwrap](https://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap) +will return the value inside the `Ok`. If the `Result` is of the `Err` +variant, unwrap will call the `panic!` macro + +``` rust +use std::fs::File; + +fn main() { + let f = File::open("hello.txt").unwrap(); +} +``` + +## expect + +[expect](https://doc.rust-lang.org/std/option/enum.Option.html#method.expect) +is almost the same as unwrap, the only difference being that it allws us +to choose the panic! error message: + +``` rust +use std::fs::File; + +fn main() { + let f = File::open("hello.txt").expect("Failed to open hello.txt"); +} +``` + +# Propagating Errors + +When you’re writing a function whose implementation calls something that +might fail, instead of handling the error within this function, you can +return the error to the calling code so that it can decide what to do. +This is known as propagating the error and gives more control to the +calling code, where there might be more information or logic that +dictates how the error should be handled than what you have available in +the context of your code. + +``` rust +#![allow(unused)] +fn main() { + use std::fs::File; + use std::io; + use std::io::Read; + + fn read_username_from_file() -> Result { + let f = File::open("hello.txt"); + + let mut f = match f { + Ok(file) => file, + Err(e) => return Err(e), + }; + + let mut s = String::new(); + + match f.read_to_string(&mut s) { + Ok(_) => Ok(s), + Err(e) => Err(e), + } + } +} +``` + +This can of course be refactored to something nicer: + +``` rust +#![allow(unused)] +fn main() { + use std::fs::File; + use std::io; + use std::io::Read; + + fn read_username_from_file() -> Result { + let mut f = File::open("hello.txt")?; + let mut s = String::new(); + f.read_to_string(&mut s)?; + Ok(s) + } +} +``` + +And this can be refactored even more: + +``` rust +#![allow(unused)] +fn main() { + use std::fs::File; + use std::io; + use std::io::Read; + + fn read_username_from_file() -> Result { + let mut s = String::new(); + + File::open("hello.txt")?.read_to_string(&mut s)?; + + Ok(s) + } +} +``` diff --git a/content/wiki/20200916172802-commonjs.md b/content/wiki/20200916172802-commonjs.md new file mode 100644 index 0000000..9694167 --- /dev/null +++ b/content/wiki/20200916172802-commonjs.md @@ -0,0 +1,31 @@ +--- +date: 2020-09-16 +id: f41437f1-359e-41c9-894b-e5785c29d729 +title: CommonJS +--- + +# Syntax + +``` javascript +const ordinal = require("ordinal"); +const {days, months} = require("date-names"); + +exports.formatDate = function(date, format) { + return format.replace(/YYYY|M(MMM)?|Do?|dddd/g, tag => { + if (tag == "YYYY") return date.getFullYear(); + if (tag == "M") return date.getMonth(); + if (tag == "MMMM") return months[date.getMonth()]; + if (tag == "D") return date.getDate(); + if (tag == "Do") return ordinal(date.getDate()); + if (tag == "dddd") return days[date.getDay()]; + }); +}; +``` + +``` javascript +const {formatDate} = require("./format-date"); + +console.log(formatDate(new Date(2017, 9, 13), + "dddd the Do")); +// → Friday the 13th +``` diff --git a/content/wiki/20200916172914-ecmascript.md b/content/wiki/20200916172914-ecmascript.md new file mode 100644 index 0000000..15f4c34 --- /dev/null +++ b/content/wiki/20200916172914-ecmascript.md @@ -0,0 +1,20 @@ +--- +date: 2020-09-16 +id: 7fa2a1e8-deae-47f9-83ee-e4f4f84eec16 +title: ECMAScript Modules +--- + +# Syntax + +``` javascript +import ordinal from "ordinal"; +import {days, months} from "date-names"; + +export function formatDate(date, format) { /* ... */ } +``` + +## Default export + +``` javascript +export default ["Winter", "Spring", "Summer", "Autumn"]; +``` diff --git a/content/wiki/20200917155644-reflection.md b/content/wiki/20200917155644-reflection.md new file mode 100644 index 0000000..ded693d --- /dev/null +++ b/content/wiki/20200917155644-reflection.md @@ -0,0 +1,9 @@ +--- +date: 2020-09-17 +id: 8fdb1d27-7983-4ab0-bda3-120715000797 +title: Reflection +--- + +# Everything you need to know about Reflection + +Avoid at all costs! diff --git a/content/wiki/20200917161757-generics.md b/content/wiki/20200917161757-generics.md new file mode 100644 index 0000000..dad236b --- /dev/null +++ b/content/wiki/20200917161757-generics.md @@ -0,0 +1,135 @@ +--- +date: 2020-09-17 +id: 9062c9c0-b2d5-4719-b15b-6fe5122b6a9e +title: Rust Generics +--- + +# Function definitions + +We read the following definition as: the function largest is generic +over some type T. This function has one parameter named list, which is a +slice of values of type T. The largest function will return a reference +to a value of the same type T. + +``` rust +fn largest(list: &[T]) -> &T { + let mut largest = list[0]; + + for item in list { + if item > largest { + largest = item; + } + } + + largest +} +``` + +# Struct definitions + +``` rust +struct Point { + x: T, + y: T, +} + +fn main() { + let integer = Point { x: 5, y: 10 }; + let float = Point { x: 1.0, y: 4.0 }; +} +``` + +A struct can also have multiple generic types: + +``` rust +struct Point { + x: T, + y: U, +} + +fn main() { + let both_integer = Point { x: 5, y: 10 }; + let both_float = Point { x: 1.0, y: 4.0 }; + let integer_and_float = Point { x: 5, y: 4.0 }; +} +``` + +# Enum Definitions + +``` rust +#![allow(unused)] +fn main() { + enum Option { + Some(T), + None, + } +} +``` + +And again with multiple generics: + +``` rust +#![allow(unused)] +fn main() { + enum Result { + Ok(T), + Err(E), + } +} +``` + +# Method Definitions + +``` rust +struct Point { + x: T, + y: T, +} + +impl Point { + fn x(&self) -> &T { + &self.x + } + fn y(&self) -> &T { + &self.y + } +} + +fn main() { + let p = Point { x: 5, y: 10 }; + + println!("p.x = {} and p.y={}", p.x(), p.y()); +} +``` + +And again with multiple generics: + +``` rust +struct Point { + x: T, + y: U, +} + +impl Point { + fn mixup(self, other: Point) -> Point { + Point { + x: self.x, + y: other.y, + } + } +} + +fn main() { + let p1 = Point { x: 5, y: 10.4 }; + let p2 = Point { x: "Hello", y: 'c' }; + + let p3 = p1.mixup(p2); + + println!("p3.x = {}, p3.y = {}", p3.x, p3.y); +} +``` + +# Performance of Code Using Generics + +The Rust compiler is very very clever and using generics has no +performance penalty diff --git a/content/wiki/20200917163203-traits.md b/content/wiki/20200917163203-traits.md new file mode 100644 index 0000000..8eda8af --- /dev/null +++ b/content/wiki/20200917163203-traits.md @@ -0,0 +1,198 @@ +--- +date: 2020-09-17 +id: 84046151-f6e2-4051-a4c5-0c82834eaa41 +title: Rust Traits Syntax +--- + +# Definition + +``` rust +#![allow(unused)] +fn main() { + pub trait Summary { + fn summarize(&self) -> String; + } +} +``` + +# Implementation + +``` rust +#![allow(unused)] +fn main() { + pub trait Summary { + fn summarize(&self) -> String; + } + + pub struct NewsArticle { + pub headline: String, + pub location: String, + pub author: String, + pub content: String, + } + + impl Summary for NewsArticle { + fn summarize(&self) -> String { + format!("{}, by {} ({})", self.headline, self.author, self.location) + } + } + + pub struct Tweet { + pub username: String, + pub content: String, + pub reply: bool, + pub retweet: bool, + } + + impl Summary for Tweet { + fn summarize(&self) -> String { + format!("{}: {}", self.username, self.content) + } + } +} +``` + +## Default Implementations + +``` rust +#![allow(unused)] +fn main() { + pub trait Summary { + fn summarize(&self) -> String { + String::from("(Read more...)") + } + } + + pub struct NewsArticle { + pub headline: String, + pub location: String, + pub author: String, + pub content: String, + } + + impl Summary for NewsArticle {} + + pub struct Tweet { + pub username: String, + pub content: String, + pub reply: bool, + pub retweet: bool, + } + + impl Summary for Tweet { + fn summarize(&self) -> String { + format!("{}: {}", self.username, self.content) + } + } +} +``` + +# Traits as Parameters + +``` rust +pub trait Summary { + fn summarize(&self) -> String; +} + +pub struct NewsArticle { + pub headline: String, + pub location: String, + pub author: String, + pub content: String, +} + +impl Summary for NewsArticle { + fn summarize(&self) -> String { + format!("{}, by {} ({})", self.headline, self.author, self.location) + } +} + +pub struct Tweet { + pub username: String, + pub content: String, + pub reply: bool, + pub retweet: bool, +} + +impl Summary for Tweet { + fn summarize(&self) -> String { + format!("{}: {}", self.username, self.content) + } +} + +pub fn notify(item: &impl Summary) { + println!("Breaking news! {}", item.summarize()); +} +``` + +## Specifying Multiple Trait Bounds + +``` rust +pub fn notify(item: &(impl Summary + Display)) { +``` + +This also works on generic types: + +``` rust +pub fn notify(item: &T) { +``` + +### Clearer Trait Bounds + +``` rust +fn some_function(t: &T, u: &U) -> i32 { +``` + +is the same as + +``` rust +fn some_function(t: &T, u: &U) -> i32 + where T: Display + Clone, + U: Clone + Debug +{ +``` + +# Return Types that Implement Traits + +``` rust +pub trait Summary { + fn summarize(&self) -> String; +} + +pub struct NewsArticle { + pub headline: String, + pub location: String, + pub author: String, + pub content: String, +} + +impl Summary for NewsArticle { + fn summarize(&self) -> String { + format!("{}, by {} ({})", self.headline, self.author, self.location) + } +} + +pub struct Tweet { + pub username: String, + pub content: String, + pub reply: bool, + pub retweet: bool, +} + +impl Summary for Tweet { + fn summarize(&self) -> String { + format!("{}: {}", self.username, self.content) + } +} + +fn returns_summarizable() -> impl Summary { + Tweet { + username: String::from("horse_ebooks"), + content: String::from( + "of course, as you probably already know, people", + ), + reply: false, + retweet: false, + } +} +``` diff --git a/content/wiki/20200918173820-mutex.md b/content/wiki/20200918173820-mutex.md new file mode 100644 index 0000000..c3d5bb1 --- /dev/null +++ b/content/wiki/20200918173820-mutex.md @@ -0,0 +1,37 @@ +--- +date: 2020-09-18 +id: 56a802e2-3871-4746-aec4-fa4bdae4d4fd +title: Golang Mutex +--- + +# Description + +[Mutex](https://golang.org/pkg/sync/#Mutex) allows up to add locks to +our data so it can be accessed safely in a concurrent manner. While +locked other threads can't access the data. `Mutexes` should generally +be used for [managing +state](https://github.com/golang/go/wiki/MutexOrChannel). + +# Syntax + +``` go +type Counter struct { + mu sync.Mutex + value int +} + +func (c *Counter) Inc() { + c.mu.Lock() + defer c.mu.Unlock() + + c.value++ +} + +func (c *Counter) Value() int { + return c.value +} + +func NewCounter() *Counter { + return &Counter{} +} +``` diff --git a/content/wiki/20200918174548-waitgroup.md b/content/wiki/20200918174548-waitgroup.md new file mode 100644 index 0000000..90b5bb5 --- /dev/null +++ b/content/wiki/20200918174548-waitgroup.md @@ -0,0 +1,54 @@ +--- +date: 2020-09-18 +id: 53c0ad13-0c19-4a84-9c67-cc31d036be4d +title: Golang WaitGroup +--- + +# Description + +A [WaitGroup](https://golang.org/pkg/sync/#WaitGroup) waits for a +collection of goroutines to finish. The main goroutine calls Add to set +the number of goroutines to wait for. Then each of the goroutines runs +and calls Done when finished. At the same time, Wait can be used to +block until all goroutines have finished. + +A WaitGroup must not be copied after first use. + +# Syntax + +``` go +type Counter struct { + mu sync.Mutex + value int +} + +func (c *Counter) Inc() { + c.mu.Lock() + defer c.mu.Unlock() + + c.value++ +} + +func (c *Counter) Value() int { + return c.value +} + +func NewCounter() *Counter { + return &Counter{} +} + +wantedCount := 1000 +counter := NewCounter() + +var wg sync.WaitGroup +wg.Add(wantedCount) + +for i := 0; i < wantedCount; i++ { + go func(w *sync.WaitGroup) { + counter.Inc() + w.Done() + }(&wg) +} + +wg.Wait() +``` diff --git a/content/wiki/20200918180634-rustc.md b/content/wiki/20200918180634-rustc.md new file mode 100644 index 0000000..3cc04ea --- /dev/null +++ b/content/wiki/20200918180634-rustc.md @@ -0,0 +1,15 @@ +--- +date: 2020-09-18 +id: 9089aff1-703d-4628-971a-5f655f7bf09f +title: Rustc +--- + +# Description + +Rustc handles Rust compilation + +# Syntax + +``` shell +rustc main.rs +``` diff --git a/content/wiki/20200918180750-cargo.md b/content/wiki/20200918180750-cargo.md new file mode 100644 index 0000000..87e6150 --- /dev/null +++ b/content/wiki/20200918180750-cargo.md @@ -0,0 +1,151 @@ +--- +date: 2020-09-18 +id: c409c0cd-5284-4333-ae99-bc351ff8ba0d +title: Cargo +--- + +# Description + +Cargo is Rust's build system and package manager. + +# Configuration + +- [Cargo.toml](20201120094652-cargo_toml) + +# Commands + +## Create project + +``` shell +cargo new hello_cargo +``` + +## Build & run project + +``` shell +cargo run +``` + +### Backtrace + +When you want to see an error backtrace set the `RUST_BACKTRACE` +environment variable: + +``` shell +RUST_BACKTRACE=1 cargo run +``` + +## Publish to Crates.io + +``` shell +cargo publish +``` + +## Install package + +``` shell +cargo install ripgrep +``` + +## Linting & testing + +Check code + +``` shell +cargo check +``` + +Testing + +``` shell +cargo test +``` + +1. Backtrace + + To backtrace set the `RUST_BACKTRACE` environment variable: + + ``` shell + RUST_BACKTRACE=1 cargo run + ``` + +2. Threads + + By default cargo runs test in parallel. For more control over this + you can pass the number of threads you want to use. For example to + only use 1 thread: + + ``` shell + cargo test -- --test=threads=1 + ``` + +3. Show output for passing tests as well as failed tests + + ``` shell + cargo test -- --show-output + ``` + +4. Pass test name to cargo (this equals test function name) + + ``` shell + cargo test one_hundred + ``` + +5. Run ignored tests + + ``` shell + cargo test -- --ignored + ``` + +Fix + +The rustfix tool is included with Rust installations and can +automatically fix some compiler warnings. + +``` shell +cargo fix +``` + +## Builds + +### Profiles + +In Rust, release profiles are predefined and customizable profiles with +different configurations that allow a programmer to have more control +over various options for compiling code. Each profile is configured +independently of the others. + +Cargo has two main profiles: the `dev` profile Cargo uses when you run +cargo build and the release profile Cargo uses when you run +`cargo build --release`. The `dev` profile is defined with good defaults +for development, and the `release` profile has good defaults for release +builds. + +1. dev + + ``` shell + cargo build + ``` + +2. build + + ``` shell + cargo build --release + ``` + +## Documentation + +See [Rust Comments](20200827190035-rust_comments) for documentation +syntax. + +### Generation + +``` shell +cargo doc +``` + +### Open in browser + +``` shell +cargo doc --open +``` diff --git a/content/wiki/20200918183524-tests.md b/content/wiki/20200918183524-tests.md new file mode 100644 index 0000000..d36027e --- /dev/null +++ b/content/wiki/20200918183524-tests.md @@ -0,0 +1,179 @@ +--- +date: 2020-09-18 +id: 23e290f6-c964-4aee-a133-232291ecdba8 +title: Tests in Rust +--- + +# Assertions + +## assert! + +``` rust +struct Rectangle { + width: u32, + height: u32, +} + +impl Rectangle { + pub fn can_hold(&self, other: &Rectangle) -> bool { + self.width > other.width && self.height > other.height + } +} + +pub struct Guess { + value: i32, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn larger_can_hold_smaller() { + let larger = Rectangle { + width: 8, + height: 7, + }; + let smaller = Rectangle { + width: 5, + height: 1, + }; + + assert!(larger.can_hold(&smaller)) + } + + #[test] + fn smaller_cannot_hold_larger() { + let larger = Rectangle { + width: 8, + height: 7, + }; + let smaller = Rectangle { + width: 5, + height: 1, + }; + + assert!(!smaller.can_hold(&larger)) + } +} +``` + +## assert~eq~! + +``` rust +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} +``` + +# Results + +## Contains + +``` rust +pub fn greeting(name: &str) -> String { + format!("Hello {}!", name) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn greeting_contains_name() { + let result = greeting("Carrol"); + assert!( + result.contains("Carrol"), + "Greeting did not countain name, value was `{}`", + result + ) + } +} +``` + +# Annotations + +## should~panic~ + +``` rust +pub struct Guess { + value: i32, +} + +impl Guess { + pub fn new(value: i32) -> Guess { + if value < 1 { + panic!( + "Guess value must be greater than or equal to 1, got {}.", + value + ); + } else if value > 100 { + panic!( + "Guess value must be less than or equal to 100, got {}.", + value + ); + } + + Guess { value } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic(expected = "Guess value must be less than or equal to 100")] + fn greater_than_100() { + Guess::new(200); + } +} + +``` + +## ignore + +This ignores tests unless specifically requested: + +``` rust +#[test] +#[ignore] +fn expensive_test() { + // code that takes an hour to run +} + +fn main() {} +``` + +# Integreation Tests + +Integration tests are their own thing and I'm too lazy to take notes now +as it's 18:59 on a Friday. See relevant chapter in [the +book](https://doc.rust-lang.org/stable/book/ch11-03-test-organization.html) +for more information. + +# Using Result \ in Tests + +This is possible for when you want to use the [question mark +operator](https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html) +in your tests: + +``` rust +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() -> Result<(), String> { + if 2 + 2 == 4 { + Ok(()) + } else { + Err(String::from("two plus two does not equal four")) + } + } +} +``` diff --git a/content/wiki/20200921154246-context.md b/content/wiki/20200921154246-context.md new file mode 100644 index 0000000..bf63621 --- /dev/null +++ b/content/wiki/20200921154246-context.md @@ -0,0 +1,70 @@ +--- +date: 2020-09-21 +id: ad20518c-1a42-4d02-8746-f42be6a46944 +title: Golang Context +--- + +# Overview + +Package context defines the Context type, which carries deadlines, +cancellation signals, and other request-scoped values across API +boundaries and between processes. + +Incoming requests to a server should create a Context, and outgoing +calls to servers should accept a Context. The chain of function calls +between them must propagate the Context, optionally replacing it with a +derived Context created using WithCancel, WithDeadline, WithTimeout, or +WithValue. When a Context is canceled, all Contexts derived from it are +also canceled. + +The WithCancel, WithDeadline, and WithTimeout functions take a Context +(the parent) and return a derived Context (the child) and a CancelFunc. +Calling the CancelFunc cancels the child and its children, removes the +parent's reference to the child, and stops any associated timers. +Failing to call the CancelFunc leaks the child and its children until +the parent is canceled or the timer fires. The go vet tool checks that +CancelFuncs are used on all control-flow paths. + +Programs that use Contexts should follow these rules to keep interfaces +consistent across packages and enable static analysis tools to check +context propagation: + +Do not store Contexts inside a struct type; instead, pass a Context +explicitly to each function that needs it. The Context should be the +first parameter, typically named ctx: + +``` go +func DoSomething(ctx context.Context, arg Arg) error { + // ... use ctx ... +} +``` + +Do not pass a nil Context, even if a function permits it. Pass +context.TODO if you are unsure about which Context to use. + +Use context Values only for request-scoped data that transits processes +and APIs, not for passing optional parameters to functions. + +The same Context may be passed to functions running in different +goroutines; Contexts are safe for simultaneous use by multiple +goroutines. + +See for example code for a server that +uses Contexts. + +# Googles take + +> At Google, we require that Go programmers pass a Context parameter as +> the first argument to every function on the call path between incoming +> and outgoing requests. This allows Go code developed by many different +> teams to interoperate well. It provides simple control over timeouts +> and cancelation and ensures that critical values like security +> credentials transit Go programs properly. + +# A saner take on this which I as a Go noob agree with + +- Context should go away for Go 2[^1] + +# Footnotes + +[^1]: diff --git a/content/wiki/20200922160850-destructuring.md b/content/wiki/20200922160850-destructuring.md new file mode 100644 index 0000000..a867f81 --- /dev/null +++ b/content/wiki/20200922160850-destructuring.md @@ -0,0 +1,16 @@ +--- +date: 2020-09-22 +id: 53649586-d844-427a-a91b-0a353631cedc +title: JavaScript Destructuring +--- + +# Variants + +- [Destructuring Arrays](20201103111509-destructuring_arrays) +- [Destructuring Objects](20201103111746-destructuring_objects) +- [Destructuring Iterables](20201103112001-destructuring_iterables) + +# Default values + +- [Destructuring Default + Values](20201103113124-destructuring_default_values) diff --git a/content/wiki/20200922162003-parameter_default_values.md b/content/wiki/20200922162003-parameter_default_values.md new file mode 100644 index 0000000..fb248fe --- /dev/null +++ b/content/wiki/20200922162003-parameter_default_values.md @@ -0,0 +1,12 @@ +--- +date: 2020-09-22 +id: d30a86d5-3788-47d0-a749-08e7edce2efd +title: JavaScript Parameter default values +--- + +# ES6 + +``` javascript +function foo(x=0, y=0) { +} +``` diff --git a/content/wiki/20200922162127-named_parameters.md b/content/wiki/20200922162127-named_parameters.md new file mode 100644 index 0000000..0f9163e --- /dev/null +++ b/content/wiki/20200922162127-named_parameters.md @@ -0,0 +1,26 @@ +--- +date: 2020-09-22 +id: dedc9e64-fe57-4c60-95b9-7df6201f4949 +title: JavaScript Named parameters +--- + +# Introduction + +Introduced with [ES6](20201030093404-es6) + +# Syntax + +``` javascript +function selectEntries({ start=0, end=-1, step=1 } = {}) { + console.log(start) + console.log(end) + console.log(step) +} + +selectEntries() +``` + +# See also + +- [Rest Operator (…) in Object + Destructuring](20201103111357-rest_operator_in_object_destructuring) diff --git a/content/wiki/20200922162500-rest_parameters.md b/content/wiki/20200922162500-rest_parameters.md new file mode 100644 index 0000000..4c7f68e --- /dev/null +++ b/content/wiki/20200922162500-rest_parameters.md @@ -0,0 +1,32 @@ +--- +date: 2020-09-22 +id: 4236e165-bf8b-45fd-9a4c-6cbb66916c45 +title: JavaScript Rest Parameters +--- + +# Introduction + +Introduced in [ES6](20201030093404-es6) + +# Syntax + +``` javascript +function logAllArguments(...args) { + for (const arg of args) { + console.log(arg); + } +} + +logAllArguments(1, 2, 3) +``` + +``` javascript +function logAllArguments(pattern, ...args) { + console.log(pattern) + for (const arg of args) { + console.log(arg); + } +} + +logAllArguments("asdf", 1, 2, 3) +``` diff --git a/content/wiki/20200922164416-numbers.md b/content/wiki/20200922164416-numbers.md new file mode 100644 index 0000000..69c42d3 --- /dev/null +++ b/content/wiki/20200922164416-numbers.md @@ -0,0 +1,24 @@ +--- +date: 2020-09-22 +id: c613c25d-3bbe-45ca-9034-b7d602770cea +title: JavaScript Numbers +--- + +# Numbers + +- [Fractional Numbers](20201116163755-fractional_numbers) + +# Notations + +- [Scientific Notation](20201116163844-scientific_notation) +- [Binary Notation](20201116164748-binary_notation) +- [Octal Notation](20201116164828-octal_notation) + +# Special Numbers + +- [Infinity](20201116163925-infinity) +- [NaN](20201116164007-nan) + +# Size + +JavaScript uses 64 bits to store number values diff --git a/content/wiki/20200922164551-strings.md b/content/wiki/20200922164551-strings.md new file mode 100644 index 0000000..62c83af --- /dev/null +++ b/content/wiki/20200922164551-strings.md @@ -0,0 +1,31 @@ +--- +date: 2020-09-22 +id: 02b70a4e-8f42-4de2-a536-dd42a42f7b47 +title: JavaScript Strings +--- + +- [String Prototype + Methods](20201112095341-javascript_string_prototype_methods) +- [String Literals](20201112100548-javascript_string_literals) +- [String Escapes](20201112101218-javascript_string_escapes) +- [Unicode](20201112101637-unicode) +- [String Iteration](20201112101851-javascript_string_iteration) +- [String To Array + Conversion](20201112102537-javascript_string_to_array_conversion) + +# Syntax + +## Regular characters + +``` javascript +console.log(`Down on the sea`) +console.log("Lie on the ocean") +console.log('Float on the ocean') +``` + +## Escaped characters + +``` javascript +console.log("This is the first line\nAnd this is the second") +console.log("A newline character is written like \"\\n\".") +``` diff --git a/content/wiki/20200922164727-booleans.md b/content/wiki/20200922164727-booleans.md new file mode 100644 index 0000000..adfdacc --- /dev/null +++ b/content/wiki/20200922164727-booleans.md @@ -0,0 +1,40 @@ +--- +date: 2020-09-22 +id: 19822398-201e-426a-86f0-48ef5a09acda +title: JavaScript Booleans +--- + +# Syntax + +``` javascript +console.log(3 > 2) +console.log(3 < 2) +``` + +Strings can also be compared + +``` javascript +console.log("Aardvark" < "Zoroaster") +``` + +Uppercase characters are always less than lower case characters, so "Z" +\< "a". Non alphabetic characters are less than alphabetic characters + +``` javascript +console.log("Zebra" < "aardvark") +console.log("!" < "aardvark") +console.log("!" < "Zebra") +console.log("3" < "Zebra") +console.log("!" < "3") +``` + +## Empty values + +There are two special empty values, null & undefined that denote the +absence of any meaningful value. They can be used interchangeably and +are an [accident of JavaScripts +design](https://medium.com/@stephenthecurt/a-brief-history-of-null-and-undefined-in-javascript-c283caab662e). + +``` javascript +console.log(null == undefined); +``` diff --git a/content/wiki/20200922164830-empty_values.md b/content/wiki/20200922164830-empty_values.md new file mode 100644 index 0000000..3f62786 --- /dev/null +++ b/content/wiki/20200922164830-empty_values.md @@ -0,0 +1,16 @@ +--- +date: 2020-09-22 +id: e250130b-d112-4557-8ac1-77f40608d22c +title: Empty values +--- + +# Syntax + +There are two special empty values, null & undefined that denote the +absence of any meaningful value. They can be used interchangeably and +are an [accident of JavaScripts +design](https://medium.com/@stephenthecurt/a-brief-history-of-null-and-undefined-in-javascript-c283caab662e). + +``` javascript +console.log(null == undefined); +``` diff --git a/content/wiki/20200923144022-closures.md b/content/wiki/20200923144022-closures.md new file mode 100644 index 0000000..3a3899f --- /dev/null +++ b/content/wiki/20200923144022-closures.md @@ -0,0 +1,45 @@ +--- +date: 2020-09-23 +id: 8353cf5c-2d2d-480a-b957-0e90da847e1c +title: Rust Closures +--- + +# Syntax + +## Long + +``` rust +fn main() { + let double_closure = |num: u32| -> u32 { 2 * num }; + + println!("2 times 3 = {}", double_closure(3)); +} +``` + +## Abbreviated + +``` rust +fn main() { + let double_closure = |num| 2 * num; + + println!("2 times 3 = {}", double_closure(3)); +} +``` + +# Closure variable scope + +Unlike [Rust functions](20200827170931-functions_macros) Closures can +capture their environment and access variables from the scope in which +they're defined: + +``` rust +fn main() { + let x = 4; + + let equal_to_x = |z| z == x; + + let y = 4; + + assert!(equal_to_x(y)); +} +``` diff --git a/content/wiki/20200923150006-iterators.md b/content/wiki/20200923150006-iterators.md new file mode 100644 index 0000000..087bcfb --- /dev/null +++ b/content/wiki/20200923150006-iterators.md @@ -0,0 +1,141 @@ +--- +date: 2020-09-23 +id: a01bfc26-dece-4741-829b-d164ba9522bb +title: Rust Iterators +--- + +# Syntax + +``` rust +fn main() { + let v1 = vec![1, 2, 3]; + + let v1_iter = v1.iter(); + + for val in v1_iter { + println!("Got: {}", val); + } +} +``` + +# Iterator Trait + +All iterators implement a [trait](20200917163203-traits) named +[Iterator](https://doc.rust-lang.org/std/iter/trait.Iterator.html) + +``` rust +#![allow(unused)] +fn main() { + pub trait Iterator { + type Item; + + fn next(&mut self) -> Option; + + // methods with default implementations elided + } +} +``` + +# Iterator methods + +## next + +``` rust +#[cfg(test)] +mod tests { + #[test] + fn iterator_demonstration() { + let v1 = vec![1, 2, 3]; + + let mut v1_iter = v1.iter(); + + assert_eq!(v1_iter.next(), Some(&1)); + assert_eq!(v1_iter.next(), Some(&2)); + assert_eq!(v1_iter.next(), Some(&3)); + assert_eq!(v1_iter.next(), None); + } +} + +fn main() {} +``` + +## sum + +``` rust +#[cfg(test)] +mod tests { + #[test] + fn iterator_sum() { + let v1 = vec![1, 2, 3]; + + let v1_iter = v1.iter(); + + let total: i32 = v1_iter.sum(); + + assert_eq!(total, 6); + } +} + +fn main() {} +``` + +# Methods that produce other Iterators + +By their nature iterators are lazy so the following won't work: + +``` rust +fn main() { + let v1: Vec = vec![1, 2, 3]; + + v1.iter().map(|x| x + 1); +} +``` + +The Iterator must be consumed, using the +[collect](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect) +method: + +``` rust +fn main() { + let v1: Vec = vec![1, 2, 3]; + + let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); + + assert_eq!(v2, vec![2, 3, 4]); +} +``` + +# Creating your own Iterators + +``` rust +struct Counter { + count: u32, +} + +impl Counter { + fn new() -> Counter { + Counter { count: 0 } + } +} + +impl Iterator for Counter { + type Item = u32; + + fn next(&mut self) -> Option { + if self.count < 5 { + self.count += 1; + Some(self.count) + } else { + None + } + } +} + +fn main() { + let counter = Counter::new(); + + for val in counter { + println!("Got: {}", val); + } +} +``` diff --git a/content/wiki/20200923153425-number.md b/content/wiki/20200923153425-number.md new file mode 100644 index 0000000..db4bc0f --- /dev/null +++ b/content/wiki/20200923153425-number.md @@ -0,0 +1,40 @@ +--- +date: 2020-09-23 +id: adb898a3-6623-4bd5-92e6-408287d8cb31 +title: JavaScript Number library +--- + +# ES6 + +## .EPSILON + +Compares floating point numbers with a tolerance for rounding errors. + +## .isInteger(num) + +``` javascript +console.log(Number.isInteger(1.05)) // false +console.log(Number.isInteger(1)) // true +console.log(Number.isInteger(-3.1)) // false +console.log(Number.isInteger(-3)) // true +``` + +## .isNaN + +Checks whether num is the value NaN. In contrast to the global function +isNaN(), it doesn’t coerce its argument to a number and is therefore +safer for non-numbers: + +``` javascript +console.log(isNaN('???')) // true +console.log(Number.isNaN('???')) // false +``` + +## .isFinite + +Determines whether the passed value is a finite number + +``` javascript +console.log(Number.isFinite(Infinity)) // false +console.log(Number.isFinite(123)) // true +``` diff --git a/content/wiki/20200923153614-math.md b/content/wiki/20200923153614-math.md new file mode 100644 index 0000000..3f4818b --- /dev/null +++ b/content/wiki/20200923153614-math.md @@ -0,0 +1,43 @@ +--- +date: 2020-09-23 +id: 1accac75-7a5c-4847-977a-f0ae63454820 +title: JavaScript Math library +--- + +# ES6 + +## .sign(x) + +### Returns + +- -1 if x is a negative number (including -Infinity). +- 0 if x is zero4. +- +1 if x is a positive number (including Infinity). +- NaN if x is NaN or not a number. + +``` javascript +console.log(Math.sign(-8)) // -a +console.log(Math.sign(3)) // 1 +console.log(Math.sign(0)) // 0 +console.log(Math.sign(NaN)) // NaN +console.log(Math.sign(-Infinity)) // -1 +console.log(Math.sign(Infinity)) // 1 +``` + +## .trunc(x) + +``` javascript +console.log(Math.trunc(3.1)) // 3 +console.log(Math.trunc(3.9)) // 3 +console.log(Math.trunc(-3.1)) // 3 +console.log(Math.trunc(-3.9)) // 3 +``` + +## .cbrt(x) + +Returns the cube root of x: + +``` javascript +console.log(Math.cbrt(8)) // 2 +console.log(Math.cbrt(27)) // 3 +``` diff --git a/content/wiki/20200928193245-embedding.md b/content/wiki/20200928193245-embedding.md new file mode 100644 index 0000000..7c62487 --- /dev/null +++ b/content/wiki/20200928193245-embedding.md @@ -0,0 +1,47 @@ +--- +date: 2020-09-28 +id: 8f08356d-b0dc-465b-b7f5-5522b5133916 +title: Golang Embedding +--- + +# Description + +[Embedding](https://golang.org/doc/effective_go.html#embedding) is Gos +answer to subclasses. There's one caveat: + +> There's an important way in which embedding differs from subclassing. +> When we embed a type, the methods of that type become methods of the +> outer type, but when they are invoked the receiver of the method is +> the inner type, not the outer one. + +# Interfaces + +``` go +type Reader interface { + Read(p []byte) (n int, err error) +} + +type Writer interface { + Write(p []byte) (n int, err error) +} + +type ReadWriter interface { + Reader + Writer +} +``` + +`ReadWriter` "extends" `Reader` & `Writer` in the example above. + +# Structs + +``` go +type ReadWriter struct { + *Reader // *bufio.Reader + *Writer // *bufio.Writer +} + +func (rw *ReadWriter) Read(p []byte) (n int, err error) { + return rw.reader.Read(p) +} +``` diff --git a/content/wiki/20200929135609-box_t.md b/content/wiki/20200929135609-box_t.md new file mode 100644 index 0000000..8cc4c8e --- /dev/null +++ b/content/wiki/20200929135609-box_t.md @@ -0,0 +1,86 @@ +--- +date: 2020-09-29 +id: d20e0dd7-ac1d-4dbb-b4e7-a6780b77bd69 +title: Box\ +--- + +# Introduction + +Boxes allow you to store data on the heap rather than the stack. What +remains on the stack is the pointer to the heap data. + +Boxes don’t have performance overhead, other than storing their data on +the heap instead of on the stack. But they don’t have many extra +capabilities either. There are three typical user cases for Boxes: + +- When you have a type whose size can’t be known at compile time and + you want to use a value of that type in a context that requires an + exact size +- When you have a large amount of data and you want to transfer + ownership but ensure the data won’t be copied when you do so +- When you want to own a value and you care only that it’s a type that + implements a particular trait rather than being of a specific type + +``` rust +fn main() { + let b = Box::new(5); + println!("b = {}", b); +} +``` + +# Reason to choose Box\ + +`Box` allows immutable or mutable borrows checked at compile time; +[Rc\](20200929145534-rc_t) allows only immutable borrows checked at +compile time; [RefCell\](20200929152628-refcell_t) allows immutable +or mutable borrows checked at runtime. + +# Usercases + +## Type whose size can't be known at compile time + +When you have a type whose size can’t be known at compile time and you +want to use a value of that type in a context that requires an exact +size. + +The following won't compile as the `List` type doesn't have a known +size: + +``` rust +enum List { + Cons(i32, List), + Nil, +} + +fn main() {} +``` + +This won't fly either: + +``` rust +enum List { + Cons(i32, List), + Nil, +} + +use crate::List::{Cons, Nil}; + +fn main() { + let list = Cons(1, Cons(2, Cons(3, Nil))); +} +``` + +With pointers all things are possible, huzzah: + +``` rust +enum List { + Cons(i32, Box), + Nil, +} + +use crate::List::{Cons, Nil}; + +fn main() { + let _list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); +} +``` diff --git a/content/wiki/20200929141711-deref_trait.md b/content/wiki/20200929141711-deref_trait.md new file mode 100644 index 0000000..1e2e26f --- /dev/null +++ b/content/wiki/20200929141711-deref_trait.md @@ -0,0 +1,109 @@ +--- +date: 2020-09-29 +id: d2d028c8-733f-4cdb-b096-89cf8b3de961 +title: Deref Trait +--- + +# Introduction + +Implementing the `Deref` trait allows you to customize the behavior of +the *dereference operator*, \* (as opposed to the multiplication or glob +operator). By implementing `Deref` in such a way that a smart pointer +can be treated like a regular reference, you can write code that +operates on references and use that code with smart pointers too: + +``` rust +fn main() { + let x = 5; + let y = &x; + + assert_eq!(5, x); + assert_eq!(5, *y); +} +``` + +# Box + +A [Box\](20200929135609-box_t) can also be used: + +``` rust +fn main() { + let x = 5; + let y = Box::new(x); + + assert_eq!(5, x); + assert_eq!(5, *y); +} +``` + +# Deref Trait + +``` rust +use std::ops::Deref; + +impl Deref for MyBox { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +struct MyBox(T); + +impl MyBox { + fn new(x: T) -> MyBox { + MyBox(x) + } +} + +fn main() { + let x = 5; + let y = MyBox::new(x); + + assert_eq!(5, x); + assert_eq!(5, *y); +} +``` + +# Deref Coercion + +*Deref coercion* is a convenience that Rust performs on arguments to +functions and methods. Deref coercion works only on types that implement +the Deref trait. Deref coercion converts such a type into a reference to +another type. For example, deref coercion can convert `&String` to +`&str` because `String` implements the `Deref` trait such that it +returns `str`. Deref coercion happens automatically when we pass a +reference to a particular type’s value as an argument to a function or +method that doesn’t match the parameter type in the function or method +definition. A sequence of calls to the `deref` method converts the type +we provided into the type the parameter needs. + +``` rust +use std::ops::Deref; + +impl Deref for MyBox { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +struct MyBox(T); + +impl MyBox { + fn new(x: T) -> MyBox { + MyBox(x) + } +} + +fn hello(name: &str) { + println!("Hello, {}!", name); +} + +fn main() { + let m = MyBox::new(String::from("Rust")); + hello(&m); +} +``` diff --git a/content/wiki/20200929142932-drop_trait.md b/content/wiki/20200929142932-drop_trait.md new file mode 100644 index 0000000..8a4ea7a --- /dev/null +++ b/content/wiki/20200929142932-drop_trait.md @@ -0,0 +1,34 @@ +--- +date: 2020-09-29 +id: a5820942-f47a-4a5e-ba83-33916cc24674 +title: Drop Trait +--- + +# Introduction + +`Drop` lets you customize what happens when a value is about to go out +of scope, ie: to release resources like files or network connections. + +# Example + +``` rust +struct CustomSmartPointer { + data: String, +} + +impl Drop for CustomSmartPointer { + fn drop(&mut self) { + println!("Dropping CustomSmartPointer with data `{}`!", self.data); + } +} + +fn main() { + let _c = CustomSmartPointer { + data: String::from("my stuff"), + }; + let _d = CustomSmartPointer { + data: String::from("other stuff"), + }; + println!("CustomSmartPointers created."); +} +``` diff --git a/content/wiki/20200929145534-rc_t.md b/content/wiki/20200929145534-rc_t.md new file mode 100644 index 0000000..d71c80e --- /dev/null +++ b/content/wiki/20200929145534-rc_t.md @@ -0,0 +1,63 @@ +--- +date: 2020-09-29 +id: 13459bc1-66f2-4eed-b987-061bd0fbeb1c +title: Rc\ +--- + +# Introduction + +In the majority of cases, ownership is clear: you know exactly which +variable owns a given value. However, there are cases when a single +value might have multiple owners. For example, in graph data structures, +multiple edges might point to the same node, and that node is +conceptually owned by all of the edges that point to it. A node +shouldn’t be cleaned up unless it doesn’t have any edges pointing to it. + +To enable multiple ownership, Rust has a type called `Rc`, which is +an abbreviation for reference counting. The `Rc` type keeps track of +the number of references to a value which determines whether or not a +value is still in use. If there are zero references to a value, the +value can be cleaned up without any references becoming invalid. + +# Reason to choose Rc\ + +`Rc` enables multiple owners of the same data; +[Box\](20200929135609-box_t) and +[RefCell\](20200929152628-refcell_t) have single owners. + +# Example + +This won't compile because b & c both share ownership of a: + +``` rust +enum List { + Cons(i32, Box), + Nil, +} + +use crate::List::{Cons, Nil}; + +fn main() { + let a = Cons(5, Box::new(Cons(10, Box::new(Nil)))); + let _b = Cons(3, Box::new(a)); + let _c = Cons(4, Box::new(a)); +} +``` + +The solution: + +``` rust +enum List { + Cons(i32, Rc), + Nil, +} + +use crate::List::{Cons, Nil}; +use std::rc::Rc; + +fn main() { + let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); + let _b = Cons(3, Rc::clone(&a)); + let _c = Cons(4, Rc::clone(&a)); +} +``` diff --git a/content/wiki/20200929152628-refcell_t.md b/content/wiki/20200929152628-refcell_t.md new file mode 100644 index 0000000..f94ef6d --- /dev/null +++ b/content/wiki/20200929152628-refcell_t.md @@ -0,0 +1,63 @@ +--- +date: 2020-09-29 +id: 16e7cc98-b9fb-40c3-b2cf-41d3035275be +title: RefCell\ +--- + +# Introduction + +*Interior mutability* is a design pattern in Rust that allows you to +mutate data even when there are immutable references to that data; +normally, this action is disallowed by the borrowing rules. To mutate +data, the pattern uses `unsafe` code inside a data structure to bend +Rust’s usual rules that govern mutation and borrowing. We can use types +that use the interior mutability pattern when we can ensure that the +borrowing rules will be followed at runtime, even though the compiler +can’t guarantee that. The `unsafe` code involved is then wrapped in a +safe API, and the outer type is still immutable. + +# Reason to choose RefCell\ + +Because `RefCell` allows mutable borrows checked at runtime, you can +mutate the value inside the `RefCell` even when the `RefCell` is +immutable. + +# Example + +This won't compile: + +``` rust +fn main() { + let x = 5; + let y = &mut x; +} +``` + +This will: + +``` rust +#[derive(Debug)] +enum List { + Cons(Rc>, Rc), + Nil, +} + +use crate::List::{Cons, Nil}; +use std::cell::RefCell; +use std::rc::Rc; + +fn main() { + let value = Rc::new(RefCell::new(5)); + + let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil))); + + let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a)); + let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a)); + + *value.borrow_mut() += 10; + + println!("a after = {:?}", a); + println!("b after = {:?}", b); + println!("c after = {:?}", c); +} +``` diff --git a/content/wiki/20200929161126-basic_annotations.md b/content/wiki/20200929161126-basic_annotations.md new file mode 100644 index 0000000..1b51e47 --- /dev/null +++ b/content/wiki/20200929161126-basic_annotations.md @@ -0,0 +1,49 @@ +--- +date: 2020-09-29 +id: 89671783-1085-4a00-9147-a377db9b19bc +title: TypeScript +--- + +# Basic Annotations + +- [Primitive Types](20200929161544-primitive_types) +- [Arrays](20200929162129-arrays) +- [Inline Type Annotation](20200929162417-inline_type_annotation) + +# Type System + +- [Ambient Declarations](20200930105954-ambient_declarations) +- [Interfaces](20200929162220-interfaces) +- [Enums](20200930110721-typescript_enums) +- [lib.d.ts](20201001105545-lib_d_ts) +- [Functions](20201001110806-typescript_functions) +- [Callable](20201001112126-typescript_callable) +- [Type Assertion](20201002101745-typescript_type_assertion) +- [Type Guard](20201002102455-typescript_type_guard) +- [Literal Types](20201002103357-typescript_literal_types) +- [Readonly](20201005171253-readonly) +- [Generics](20200929163051-typescript_generics) +- [Intersection Type](20200929163316-typescript_intersection_type) +- [Tuple Type](20200929163624-typescript_tuple_type) +- [TypeScript Type Alias](20200929163825-typescript_type_alias) +- [Never Type](20201007095614-typescript_never_type) +- [Index Signatures](20201008092225-index_signatures) +- [Classes](20201009104411-typescript_classes) + +## Unions + +- [Union Type](20200929163219-typescript_union_type) +- [Discriminated Union](20201007101133-typescript_discriminated_union) + +# Related pages + +- [JavaScript](20200613170905-javascript) + +# Books + +- [TypeScript Deep Dive](https://basarat.gitbook.io/typescript/) +- [Style Guide](https://basarat.gitbook.io/typescript/styleguide) + +# Changes + +- [TypeScript 4.0](20201009104050-typescript_4_0) diff --git a/content/wiki/20200929161126-typescript.md b/content/wiki/20200929161126-typescript.md new file mode 100644 index 0000000..9dc3786 --- /dev/null +++ b/content/wiki/20200929161126-typescript.md @@ -0,0 +1,67 @@ +--- +date: 2020-09-29 +id: 547d6700-cedd-4273-9f12-1fd4da96b695 +title: TypeScript +--- + +# Types + +- [Arrays](20200929162129-arrays) +- [Enums](20200930110721-typescript_enums) +- [Generics](20200929163051-typescript_generics) +- [Intersection Type](20200929163316-typescript_intersection_type) +- [Literal Types](20201002103357-typescript_literal_types) +- [Mapped Type](20201124085335-typescript_mapped_type) +- [Never Type](20201007095614-typescript_never_type) +- [Primitive Types](20200929161544-primitive_types) +- [Recursive Conditional + Types](20201125085727-typescript_recursive_conditional_types) +- [Tuple Type](20200929163624-typescript_tuple_type) +- [Union Type](20200929163219-typescript_union_type) + +# Objects + +- [Classes](20201009104411-typescript_classes) +- [Inline Type Annotation](20200929162417-inline_type_annotation) +- [Interfaces](20200929162220-interfaces) + +# Functions + +- [Functions](20201001110806-typescript_functions) + +# Declarations + +- [Ambient Declarations](20200930105954-ambient_declarations) +- [lib.d.ts](20201001105545-lib_d_ts) + +# Syntax + +- [Callable](20201001112126-typescript_callable) +- [Discriminated Union](20201007101133-typescript_discriminated_union) +- [Index Signatures](20201008092225-index_signatures) +- [Readonly](20201005171253-readonly) +- [Type Alias](20200929163825-typescript_type_alias) +- [Type Assertion](20201002101745-typescript_type_assertion) +- [Type Guard](20201002102455-typescript_type_guard) + +# Clauses + +- [as](20201124095453-typescript_as_clause) + +# Keywords + +- [in](20201124090450-typescript_in_operator) + +# Configuration + +- [Flags](20201127101043-typescript_flags) + +# Books + +- [TypeScript Deep Dive](https://basarat.gitbook.io/typescript/) +- [Style Guide](https://basarat.gitbook.io/typescript/styleguide) + +# Changes + +- [4.0](20201009104050-typescript_4_0) +- [4.1](20201123094735-typescript_4_1) diff --git a/content/wiki/20200929161544-primitive_types.md b/content/wiki/20200929161544-primitive_types.md new file mode 100644 index 0000000..17d82a4 --- /dev/null +++ b/content/wiki/20200929161544-primitive_types.md @@ -0,0 +1,35 @@ +--- +date: 2020-09-29 +id: 8809980a-615d-453f-bc63-2f890fca03b8 +title: TypeScript primitive types +--- + +# Syntax + +## Number + +``` typescript +var num: number +num = 123 +num = 123.24 +num = '123' / Error +``` + +## String + +``` typescript +var str: string + +str = '123' +str = 123 // Error +``` + +## Boolean + +``` typescript +var bool: boolean + +bool = true +bool = false +bool = 'tralala' // Error +``` diff --git a/content/wiki/20200929162129-arrays.md b/content/wiki/20200929162129-arrays.md new file mode 100644 index 0000000..86351f1 --- /dev/null +++ b/content/wiki/20200929162129-arrays.md @@ -0,0 +1,21 @@ +--- +date: 2020-09-29 +id: aea39282-589d-49ab-8b50-c55c7681f500 +title: TypeScript Arrays +--- + +# Syntax + +``` typescript +var boolArray: boolean[]; + +boolArray = [true, false]; +console.log(boolArray[0]); // true +console.log(boolArray.length); // 2 +boolArray[1] = true; +boolArray = [false, false]; + +boolArray[0] = 'false'; // Error! +boolArray = 'false'; // Error! +boolArray = [true, 'false']; // Error! +``` diff --git a/content/wiki/20200929162220-interfaces.md b/content/wiki/20200929162220-interfaces.md new file mode 100644 index 0000000..539efe7 --- /dev/null +++ b/content/wiki/20200929162220-interfaces.md @@ -0,0 +1,40 @@ +--- +date: 2020-09-29 +id: 1bdd832a-3dee-4b31-9192-c51cde8a4b66 +title: TypeScript Interfaces +--- + +# Example + +``` typescript +interface Name { + first: string; + second: string; +} + +var name: Name; +name = { + first: 'John', + second: 'Doe' +}; + +name = { // Error : `second` is missing + first: 'John' +}; +name = { // Error : `second` is the wrong type + first: 'John', + second: 1337 +}; +``` + +## Class implementing interface + +``` typescript +interface Point { + x: number; y: number; +} + +class MyPoint implements Point { + x: number; y: number; // Same as Point +} +``` diff --git a/content/wiki/20200929162417-inline_type_annotation.md b/content/wiki/20200929162417-inline_type_annotation.md new file mode 100644 index 0000000..8c89933 --- /dev/null +++ b/content/wiki/20200929162417-inline_type_annotation.md @@ -0,0 +1,26 @@ +--- +date: 2020-09-29 +id: 01e5c8e4-5227-4565-96e5-94a4bb6240ea +title: TypeScript Inline Type Annotation +--- + +# Syntax + +``` typescript +var name: { + first: string; + second: string; +}; +name = { + first: 'John', + second: 'Doe' +}; + +name = { // Error : `second` is missing + first: 'John' +}; +name = { // Error : `second` is the wrong type + first: 'John', + second: 1337 +}; +``` diff --git a/content/wiki/20200929163051-typescript_generics.md b/content/wiki/20200929163051-typescript_generics.md new file mode 100644 index 0000000..6bff77e --- /dev/null +++ b/content/wiki/20200929163051-typescript_generics.md @@ -0,0 +1,60 @@ +--- +date: 2020-09-29 +id: aacdac15-4e00-4d75-9888-79b23bb47498 +title: TypeScript Generics +--- + +# Examples + +## Function level + +``` typescript +function reverse(items: T[]): T[] { + var toreturn = []; + for (let i = items.length - 1; i >= 0; i--) { + toreturn.push(items[i]); + } + return toreturn; +} + +var sample = [1, 2, 3]; +var reversed = reverse(sample); +console.log(reversed); // 3,2,1 + +// Safety! +reversed[0] = '1'; // Error! +reversed = ['1', '2']; // Error! + +reversed[0] = 1; // Okay +reversed = [1, 2]; // Okay +``` + +## Class level + +``` typescript +/** A class definition with a generic parameter */ +class Queue { + private data = []; + push(item: T) { this.data.push(item); } + pop(): T | undefined { return this.data.shift(); } +} + +/** Again sample usage */ +const queue = new Queue(); +queue.push(0); +queue.push("1"); // ERROR : cannot push a string. Only numbers allowed +``` + +## Member functions + +``` typescript +class Utility { + reverse(items: T[]): T[] { + var toreturn = []; + for (let i = items.length - 1; i >= 0; i--) { + toreturn.push(items[i]); + } + return toreturn; + } +} +``` diff --git a/content/wiki/20200929163219-typescript_union_type.md b/content/wiki/20200929163219-typescript_union_type.md new file mode 100644 index 0000000..76204d3 --- /dev/null +++ b/content/wiki/20200929163219-typescript_union_type.md @@ -0,0 +1,20 @@ +--- +date: 2020-09-29 +id: 2dae9e2e-90c4-4d1b-a992-baacaa053b21 +title: TypeScript Union Type +--- + +# Syntax + +``` typescript +function formatCommandline(command: string[]|string) { + var line = ''; + if (typeof command === 'string') { + line = command.trim(); + } else { + line = command.join(' ').trim(); + } + + // Do stuff with line: string +} +``` diff --git a/content/wiki/20200929163316-typescript_intersection_type.md b/content/wiki/20200929163316-typescript_intersection_type.md new file mode 100644 index 0000000..5aad9d5 --- /dev/null +++ b/content/wiki/20200929163316-typescript_intersection_type.md @@ -0,0 +1,27 @@ +--- +date: 2020-09-29 +id: e3434ce4-0210-4a9b-92ed-9da1e5000bac +title: TypeScript Intersection Type +--- + +# Description + +`extend` is a very common pattern in +[JavaScript](20200613170905-javascript) where you take two +[objects](20200826201605-objects) and create a new one that has the +features of both these objects. An `Intersection Type` allows you to use +this pattern in a safe way. + +# Syntax + +``` typescript +function extend(first: T, second: U): T & U { + return { ...first, ...second }; +} + +const x = extend({ a: "hello" }, { b: 42 }); + +// x now has both `a` and `b` +const a = x.a; +const b = x.b; +``` diff --git a/content/wiki/20200929163624-typescript_tuple_type.md b/content/wiki/20200929163624-typescript_tuple_type.md new file mode 100644 index 0000000..be23e5d --- /dev/null +++ b/content/wiki/20200929163624-typescript_tuple_type.md @@ -0,0 +1,46 @@ +--- +date: 2020-09-29 +id: 894dff80-c2c8-4408-b05f-3079ca833b3c +title: TypeScript Tuple Type +--- + +# Syntax + +## Basic + +``` typescript +var nameNumber: [string, number]; +var name: string; +var num: number; + +// Okay +nameNumber = ['Jenny', 8675309]; + +// Error! +nameNumber = ['Jenny', '867-5309']; + +var [name, num] = nameNumber; +``` + +## Rest elements + +[Rest](20200922162500-rest_parameters) elements can occur anywhere in a +tuple, not just at the end: + +``` typescript +type Strings = [string, string]; +type Numbers = [number, number]; + +// [string, string, number, number, boolean] +type StrStrNumNumBool = [...Strings, ...Numbers, boolean]; +``` + +## Labels + +``` typescript +type Range = [start: number, end: number]; +``` + +``` typescript +type Foo = [first: number, second?: string, ...rest: any[]]; +``` diff --git a/content/wiki/20200929163825-typescript_type_alias.md b/content/wiki/20200929163825-typescript_type_alias.md new file mode 100644 index 0000000..d7a1717 --- /dev/null +++ b/content/wiki/20200929163825-typescript_type_alias.md @@ -0,0 +1,29 @@ +--- +date: 2020-09-29 +id: 188e8fe7-0f96-4b05-97f2-fc2a760ccab4 +title: TypeScript Type Alias +--- + +# Description + +The make your own Sundae of Types. + +# Sytax + +``` typescript +type StrOrNum = string|number; + +// Usage: just like any other notation +var sample: StrOrNum; +sample = 123; +sample = '123'; + +// Just checking +sample = true; // Error! +``` + +``` typescript +type Text = string | { text: string }; +type Coordinates = [number, number]; +type Callback = (data: string) => void; +``` diff --git a/content/wiki/20200930105954-ambient_declarations.md b/content/wiki/20200930105954-ambient_declarations.md new file mode 100644 index 0000000..9afb61e --- /dev/null +++ b/content/wiki/20200930105954-ambient_declarations.md @@ -0,0 +1,28 @@ +--- +date: 2020-09-30 +id: e1048c95-3baa-445e-a943-bff7b86a0f29 +title: Ambient Declarations +--- + +# Introduction + +Ambient declarations allow you to safely use existing popular JavaScript +libraries and incrementally migrate your +JavaScript/CoffeeScript/Other-Compile-To-Js-Language project to +TypeScript. + +# Declaration Files + +Syntax is simple: + +``` typescript +declare var foo: any +``` + +Declarations can be put in a `.ts` or `.d.ts` file, ie: `global.d.ts` or +`vendor.d.ts` + +# Best Practices + +- Use `.d.ts` +- Use [interfaces](20200929162220-interfaces) where possible diff --git a/content/wiki/20200930110721-typescript_enums.md b/content/wiki/20200930110721-typescript_enums.md new file mode 100644 index 0000000..39632a8 --- /dev/null +++ b/content/wiki/20200930110721-typescript_enums.md @@ -0,0 +1,22 @@ +--- +date: 2020-09-30 +id: 4e52541b-5119-4228-97b2-f17f5a23b138 +title: TypeScript Enums +--- + +# Syntax + +``` typescript +enum CardSuit { + Clubs, + Diamonds, + Hearts, + Spades +} + +// Sample usage +var card = CardSuit.Clubs; + +// Safety +card = "not a member of card suit"; // Error : string is not assignable to type `CardSuit` +``` diff --git a/content/wiki/20200930121904-rust_threads.md b/content/wiki/20200930121904-rust_threads.md new file mode 100644 index 0000000..95fc723 --- /dev/null +++ b/content/wiki/20200930121904-rust_threads.md @@ -0,0 +1,127 @@ +--- +date: 2020-09-30 +id: 90fe2657-017e-41f6-9ac3-e4cb4590dc44 +title: Rust Threads +--- + +# Introduction + +Programming languages implement threads in a few different ways. Many +operating systems provide an API for creating new threads. This model +where a language calls the operating system APIs to create threads is +sometimes called *1:1*, meaning one operating system thread per one +language thread. + +Many programming languages provide their own special implementation of +threads. Programming language-provided threads are known as green +threads, and languages that use these green threads will execute them in +the context of a different number of operating system threads. For this +reason, the green-threaded model is called the *M:N* model: there are M +green threads per N operating system threads, where M and N are not +necessarily the same number. + +Each model has its own advantages and trade-offs, and the trade-off most +important to Rust is runtime support. Runtime is a confusing term and +can have different meanings in different contexts. + +In this context, by *runtime* we mean code that is included by the +language in every binary. This code can be large or small depending on +the language, but every non-assembly language will have some amount of +runtime code. For that reason, colloquially when people say a language +has “no runtime,” they often mean “small runtime.” Smaller runtimes have +fewer features but have the advantage of resulting in smaller binaries, +which make it easier to combine the language with other languages in +more contexts. Although many languages are okay with increasing the +runtime size in exchange for more features, Rust needs to have nearly no +runtime and cannot compromise on being able to call into C to maintain +performance. + +The green-threading M:N model requires a larger language runtime to +manage threads. As such, the Rust standard library only provides an +implementation of 1:1 threading. Because Rust is such a low-level +language, there are crates that implement M:N threading if you would +rather trade overhead for aspects such as more control over which +threads run when and lower costs of context switching, for example. + +# Examples + +## Creating a New Thread + +``` rust +use std::thread; +use std::time::Duration; + +fn main() { + thread::spawn(|| { + for i in 1..10 { + println!("hi number {} from the spawned thread!", i); + thread::sleep(Duration::from_millis(1)); + } + }); + + for i in 1..5 { + println!("hi number {} from the main thread!", i); + thread::sleep(Duration::from_millis(1)); + } +} +``` + +## Waiting for All Threads To Finish + +``` rust +use std::thread; +use std::time::Duration; + +fn main() { + let handle = thread::spawn(|| { + for i in 1..10 { + println!("hi number {} from the spawned thread!", i); + thread::sleep(Duration::from_millis(1)); + } + }); + + for i in 1..5 { + println!("hi number {} from the main thread!", i); + thread::sleep(Duration::from_millis(1)); + } + + handle.join().unwrap(); +} +``` + +``` rust +use std::thread; +use std::time::Duration; + +fn main() { + let handle = thread::spawn(|| { + for i in 1..10 { + println!("hi number {} from the spawned thread!", i); + thread::sleep(Duration::from_millis(1)); + } + }); + + handle.join().unwrap(); + + for i in 1..5 { + println!("hi number {} from the main thread!", i); + thread::sleep(Duration::from_millis(1)); + } +} +``` + +## using move Closures + +``` rust +use std::thread; + +fn main() { + let v = vec![1, 2, 3]; + + let handle = thread::spawn(move || { + println!("Here's a vector: {:?}", v); + }); + + handle.join().unwrap(); +} +``` diff --git a/content/wiki/20200930123003-message_passing.md b/content/wiki/20200930123003-message_passing.md new file mode 100644 index 0000000..2653b0c --- /dev/null +++ b/content/wiki/20200930123003-message_passing.md @@ -0,0 +1,105 @@ +--- +date: 2020-09-30 +id: 20a442a2-657a-4337-b82f-5b7f29eb4607 +title: Rust message passing +--- + +# Example + +## Sending single value + +``` rust +use std::sync::mpsc; +use std::thread; + +fn main() { + let (tx, rx) = mpsc::channel(); + + thread::spawn(move || { + let val = String::from("hi"); + tx.send(val).unwrap(); + }); + + let received = rx.recv().unwrap(); + println!("Got: {}", received); +} +``` + +## Sending multiple values + +``` rust +use std::sync::mpsc; +use std::thread; +use std::time::Duration; + +fn main() { + let (tx, rx) = mpsc::channel(); + + thread::spawn(move || { + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("thread"), + ]; + + for val in vals { + tx.send(val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + for received in rx { + println!("Got: {}", received); + } +} +``` + +## Creating multiple Producers + +``` rust +use std::sync::mpsc; +use std::thread; +use std::time::Duration; + +fn main() { + // --snip-- + + let (tx, rx) = mpsc::channel(); + + let tx1 = mpsc::Sender::clone(&tx); + thread::spawn(move || { + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("thread"), + ]; + + for val in vals { + tx1.send(val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + thread::spawn(move || { + let vals = vec![ + String::from("more"), + String::from("messages"), + String::from("for"), + String::from("you"), + ]; + + for val in vals { + tx.send(val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + for received in rx { + println!("Got: {}", received); + } + + // --snip-- +} +``` diff --git a/content/wiki/20200930123749-rust_shared_state_concurrency.md b/content/wiki/20200930123749-rust_shared_state_concurrency.md new file mode 100644 index 0000000..cbbb974 --- /dev/null +++ b/content/wiki/20200930123749-rust_shared_state_concurrency.md @@ -0,0 +1,52 @@ +--- +date: 2020-09-30 +id: 6e53ba2a-20e7-4d81-8047-8eecaffc76f7 +title: Rust Shared-State Concurrency +--- + +# Mutex\ + +## Single thread example + +``` rust +use std::sync::Mutex; + +fn main() { + let m = Mutex::new(5); + + { + let mut num = m.lock().unwrap(); + *num = 6; + } + + println!("m = {:?}", m); +} +``` + +## Multiple thread example + +``` rust +use std::sync::{Arc, Mutex}; +use std::thread; + +fn main() { + let counter = Arc::new(Mutex::new(0)); + let mut handles = vec![]; + + for _ in 0..10 { + let counter = Arc::clone(&counter); + let handle = thread::spawn(move || { + let mut num = counter.lock().unwrap(); + + *num += 1; + }); + handles.push(handle); + } + + for handle in handles { + handle.join().unwrap(); + } + + println!("Result: {}", *counter.lock().unwrap()); +} +``` diff --git a/content/wiki/20201001105545-lib_d_ts.md b/content/wiki/20201001105545-lib_d_ts.md new file mode 100644 index 0000000..20c3b2b --- /dev/null +++ b/content/wiki/20201001105545-lib_d_ts.md @@ -0,0 +1,49 @@ +--- +date: 2020-10-01 +id: afc1ca85-af24-4ef6-bcd8-91193c4fbd32 +title: lib.d.ts +--- + +# Introduction + +This is where TypeScript "cheats" and ships with a file called +[lib.d.ts](https://github.com/microsoft/TypeScript/blob/master/lib/lib.d.ts). +This file contains ambient declarations for a whole bunch of common +[JavaScript](20200613170905-javascript) constructs present in JavaScript +runtimes and the DOM. + +- This file is automatically included in the compilation context of a + TypeScript project. +- The objective of this file is to make it easy for you to start + writing type checked JavaScript code. + +# Modifying Native Types + +If you want to be a clever clogs you can add stuff to the interfaces in +lib.d.ts by creating a global module (ie: `global.d.ts`) + +# Example + +## lib.d.ts magic + +The following code is only possible because of lib.d.ts. If it's used +with the `nolib` option, TypeScript doesn't know that all JavaScript +objects have a `toString` function. + + var foo = 123; + var bar = foo.toString(); + +## Example of what's in the lib.d.ts + +``` typescript +declare var window: Window; + +interface Window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64 { + animationStartTime: number; + applicationCache: ApplicationCache; + clientInformation: Navigator; + closed: boolean; + crypto: Crypto; + // so on and so forth... +} +``` diff --git a/content/wiki/20201001110806-typescript_functions.md b/content/wiki/20201001110806-typescript_functions.md new file mode 100644 index 0000000..e4afccf --- /dev/null +++ b/content/wiki/20201001110806-typescript_functions.md @@ -0,0 +1,205 @@ +--- +date: 2020-10-01 +id: 6df4db64-8ad2-4190-9d4e-3e6f77021a31 +title: TypeScript Functions +--- + +# TypeScript 4.0 + +## Variadic Tuple Types + +### Pre 4.0 situation + +Consider the following +[function](20201006111125-javascript_function_declerations) using +[Tuples](20200929163624-typescript_tuple_type): + +``` javascript +function concat(arr1, arr2) { + return [...arr1, ...arr2]; +} +``` + +The only way to type this in [TypeScript](20200929161126-typescript) +used to be: + +``` typescript +function concat(arr1: [], arr2: []): []; +function concat(arr1: [A], arr2: []): [A]; +function concat(arr1: [A, B], arr2: []): [A, B]; +function concat(arr1: [A, B, C], arr2: []): [A, B, C]; +function concat(arr1: [A, B, C, D], arr2: []): [A, B, C, D]; +function concat(arr1: [A, B, C, D, E], arr2: []): [A, B, C, D, E]; +function concat(arr1: [A, B, C, D, E, F], arr2: []): [A, B, C, D, E, F];) + +function concat(arr1: [], arr2: [A2]): [A2]; +function concat(arr1: [A1], arr2: [A2]): [A1, A2]; +function concat(arr1: [A1, B1], arr2: [A2]): [A1, B1, A2]; +function concat(arr1: [A1, B1, C1], arr2: [A2]): [A1, B1, C1, A2]; +function concat(arr1: [A1, B1, C1, D1], arr2: [A2]): [A1, B1, C1, D1, A2]; +function concat(arr1: [A1, B1, C1, D1, E1], arr2: [A2]): [A1, B1, C1, D1, E1, A2]; +function concat(arr1: [A1, B1, C1, D1, E1, F1], arr2: [A2]): [A1, B1, C1, D1, E1, F1, A2]; +``` + +### Post 4.0 situation + +1. Tail example + + Consider the following example: + + ``` javascript + function tail(arg) { + const [_, ...result] = arg; + return result + } + ``` + + TypeScript 4.0 bring 2 changes here. + + 1. Changes + + 1. Generic spreads in tuple types + + The [spreads](20201014094144-spread) in [tuple + type](20200929163624-typescript_tuple_type) syntax to be + [generic](20200929163051-typescript_generics): + + ``` typescript + function tail(arr: readonly [any, ...T]) { + const [_ignored, ...rest] = arr; + return rest; + } + + const myTuple = [1, 2, 3, 4] as const; + const myArray = ["hello", "world"]; + + // type [2, 3, 4] + const r1 = tail(myTuple); + + // type [2, 3, 4, ...string[]] + const r2 = tail([...myTuple, ...myArray] as const); + ``` + + 2. Rest elements can occur anywhre in a tuple + + [Rest](20200922162500-rest_parameters) elements can occur + anywhere in a [tuple](20200929163624-typescript_tuple_type), + not just at the end: + + ``` typescript + type Strings = [string, string]; + type Numbers = [number, number]; + + // [string, string, number, number, boolean] + type StrStrNumNumBool = [...Strings, ...Numbers, boolean]; + ``` + +2. Concat example + + Note that in cases when we [spread](20201014094144-spread) in a type + without a known length, the resulting type becomes unbounded as + well, and all the following elements factor into the resulting rest + element type. + + ``` typescript + type Strings = [string, string]; + type Numbers = number[] + + // [string, string, ...Array] + type Unbounded = [...Strings, ...Numbers, boolean]; + ``` + + Therefore the `concat()` example can be typed with: + + ``` typescript + type Arr = readonly any[]; + + function concat(arr1: T, arr2: U): [...T, ...U] { + return [...arr1, ...arr2]; + } + ``` + +# Examples + +## Parameter annotations + +``` typescript +function tralala(tra: number, la: number) {} +``` + +## Return type annotation + +``` typescript +interface Foo { + bar: string +} + +function tralala(): Foo { + return {bar: 'tralala'} +} +``` + +## Optional Parameters + +``` typescript +function foo(bar: number, optional?: string) {} +``` + +``` typescript +function foo(bar: number, optional: string = 'This is an optional string') {} +``` + +## Overloading + +This is for documentation purposes but imho just makes things more +confusing. + +``` typescript +// Overloads +function padding(all: number); +function padding(topAndBottom: number, leftAndRight: number); +function padding(top: number, right: number, bottom: number, left: number); +// Actual implementation that is a true representation of all the cases the function body needs to handle +function padding(a: number, b?: number, c?: number, d?: number) { + if (b === undefined && c === undefined && d === undefined) { + b = c = d = a; + } + else if (c === undefined && d === undefined) { + c = a; + d = b; + } + return { + top: a, + right: b, + bottom: c, + left: d + }; +} + +padding(1); // Okay: all +padding(1,1); // Okay: topAndBottom, leftAndRight +padding(1,1,1,1); // Okay: top, right, bottom, left + +padding(1,1,1); // Error: Not a part of the available overloads +``` + +## Declaring Functions + +Use this to declare function type without providing implementation: + +``` typescript +type LongHand = { + (a: number): number; +}; + +type ShortHand = (a: number) => number; +``` + +Overloading is supported as well: + +``` typescript +type LongHandAllowsOverloadDeclarations = { + (a: number): number; + (a: string): string; +}; +``` diff --git a/content/wiki/20201001112126-typescript_callable.md b/content/wiki/20201001112126-typescript_callable.md new file mode 100644 index 0000000..f01dd15 --- /dev/null +++ b/content/wiki/20201001112126-typescript_callable.md @@ -0,0 +1,78 @@ +--- +date: 2020-10-01 +id: afb5a8ff-045c-48f1-9b9e-e5bb55f4a572 +title: TypeScript Callable +--- + +# Examples + +## Basic + +``` typescript +interface ReturnString { + (): string +} + +declare const foo: ReturnString; +const bar = foo(); // bar is inferred as a string +``` + +``` typescript +interface Complex { + (foo: string, bar?: number, ...others: boolean[]): number; +} +``` + +## Overloading + +``` typescript +interface Overloaded { + (foo: string): string + (foo: number): number +} + +// example implementation +function stringOrNumber(foo: number): number; +function stringOrNumber(foo: string): string; +function stringOrNumber(foo: any): any { + if (typeof foo === 'number') { + return foo * foo; + } else if (typeof foo === 'string') { + return `hello ${foo}`; + } +} + +const overloaded: Overloaded = stringOrNumber; + +// example usage +const str = overloaded(''); // type of `str` is inferred as `string` +const num = overloaded(123); // type of `num` is inferred as `number` +``` + +``` typescript +const overloaded: { + (foo: string): string + (foo: number): number +} = (foo: any) => foo; +``` + +## Arrow Syntax + +``` typescript +const simple: (foo: number) => string + = (foo) => foo.toString(); +``` + +## Newable + +Newable is just a special type of callable type annotation with the +prefix new. It simply means that you need to invoke with new: + +``` typescript +interface CallMeWithNewToGetString { + new(): string +} +// Usage +declare const Foo: CallMeWithNewToGetString; +const bar = new Foo(); // bar is inferred to be of type string +``` diff --git a/content/wiki/20201002101745-typescript_type_assertion.md b/content/wiki/20201002101745-typescript_type_assertion.md new file mode 100644 index 0000000..4ff71f2 --- /dev/null +++ b/content/wiki/20201002101745-typescript_type_assertion.md @@ -0,0 +1,23 @@ +--- +date: 2020-10-02 +id: f86e5e6b-8a05-4dc5-9954-743fabef33bc +title: TypeScript Type Assertion +--- + +# Introduction + +If you're a Mr(s). Know It All and want to tell the compiler what to do +you can use `Type Assertions`. + +# Syntax + +``` typescript +interface Foo { + bar: number; + bas: string; +} + +var foo = {} as Foo; +foo.bar = 123; +foo.bas = 'hello'; +``` diff --git a/content/wiki/20201002102455-typescript_type_guard.md b/content/wiki/20201002102455-typescript_type_guard.md new file mode 100644 index 0000000..d088b74 --- /dev/null +++ b/content/wiki/20201002102455-typescript_type_guard.md @@ -0,0 +1,23 @@ +--- +date: 2020-10-02 +id: 4adf622e-b34a-4a24-ac9e-1c754a1fd8d5 +title: TypeScript Type Guard +--- + +# Introduction + +Use `Type Guards` to narrow down the type of an object within a +conditional block. + +# Operators + +- [TypeScript in Operator](20201124090450-typescript_in_operator) + +# Syntax + +- [TypeScript Literal Type + Guard](20201124091025-typescript_literal_type_guard) +- [TypeScript + strictNullChecks](20201124091530-typescript_strictnullchecks) +- [TypeScript User Defined Type + Guards](20201124091740-typescript_user_defined_type_guards) diff --git a/content/wiki/20201002103357-typescript_literal_types.md b/content/wiki/20201002103357-typescript_literal_types.md new file mode 100644 index 0000000..fea1b15 --- /dev/null +++ b/content/wiki/20201002103357-typescript_literal_types.md @@ -0,0 +1,56 @@ +--- +date: 2020-10-02 +id: d6b6005e-bd66-4524-b1f4-d3b27c8d9c46 +title: TypeScript Literal Types +--- + +# Introduction + +Literals are *exact* values that are JavaScript primitives. + +# Types + +- [String](20201123100551-typescript_string_literal_type) +- [Boolean](20201123100939-typescript_boolean_literal_type) +- [Number](20201123101123-typescript_number_literal_type) +- [Template Literal + String](20201123101810-typescript_template_literal_string_type) + +# Type Guards + +- [TypeScript Literal Type + Guard](20201124091025-typescript_literal_type_guard) + +# Inference + +TypeScript is not all knowing. The following won't fly: + +``` typescript +function iTakeFoo(foo: 'foo') { } +const test = { + someProp: 'foo' +}; +iTakeFoo(test.someProp); // Error: Argument of type string is not assignable to parameter of type 'foo' +``` + +TypeScript infers `test` to be of type `{someProp: string`}. There are a +couple of ways to fix this: + +``` typescript +function iTakeFoo(foo: 'foo') { } +const test = { + someProp: 'foo' as 'foo' +}; +iTakeFoo(test.someProp); // Okay! +``` + +``` typescript +function iTakeFoo(foo: 'foo') { } +type Test = { + someProp: 'foo', +} +const test: Test = { // Annotate - inferred someProp is always === 'foo' + someProp: 'foo' +}; +iTakeFoo(test.someProp); // Okay! +``` diff --git a/content/wiki/20201005171253-readonly.md b/content/wiki/20201005171253-readonly.md new file mode 100644 index 0000000..761fbf2 --- /dev/null +++ b/content/wiki/20201005171253-readonly.md @@ -0,0 +1,69 @@ +--- +date: 2020-10-05 +id: c0bc64a7-f2dc-4e2e-afb9-5dbc63eb8287 +title: Readonly +--- + +# Introduction + +[TypeScript's](20200929161126-typescript) type system allows you to mark +individual properties on [interfaces](20200929162220-interfaces), +[types](20200929163825-typescript_type_alias) and +[class](20201009104411-typescript_classes) properties as `readonly`. + +# Examples + +## interface + +``` typescript +function foo(config: { + readonly bar: number, + readonly bas: number}) {// .. +} + +let config = { bar: 123, bas: 123 }; +foo(config); +// You can be sure that `config` isn't changed 🌹 +``` + +## type + +``` typescript +type Foo = { + readonly bar: number; + readonly bas: number; +} +​ +// Initialization is okay +let foo: Foo = { bar: 123, bas: 456 }; +​ +// Mutation is not +foo.bar = 456; // Error: Left-hand side of assignment expression cannot be a constant or a read-only property +``` + +## class property + +``` typescript +class Foo { + readonly bar = 1; // OK + readonly baz: string; + constructor() { + this.baz = "hello"; // OK + } +} +``` + +``` typescript +type Foo = { + bar: number; + bas: number; +} + +type FooReadonly = Readonly; + +let foo: Foo = {bar: 123, bas: 456}; +let fooReadonly: FooReadonly = {bar: 123, bas: 456}; + +foo.bar = 456; // Okay +fooReadonly.bar = 456; // ERROR: bar is readonly +``` diff --git a/content/wiki/20201006102934-pattern_syntax.md b/content/wiki/20201006102934-pattern_syntax.md new file mode 100644 index 0000000..362cfd9 --- /dev/null +++ b/content/wiki/20201006102934-pattern_syntax.md @@ -0,0 +1,365 @@ +--- +date: 2020-10-06 +id: 8c351588-1dc2-4955-86b5-a13181367cf9 +title: Rust Pattern Syntax +--- + +# Examples + +## Matching Literals + +``` rust +fn main() { + let x = 1; + + match x { + 1 => println!("one"), + 2 => println!("two"), + 3 => println!("three"), + _ => println!("anything"), + } +} +``` + +## Matching Named Variables + +``` rust +fn main() { + let x = Some(5); + let y = 10; + + match x { + Some(50) => println!("Got 50"), + Some(y) => println!("Matched, y = {:?}", y), + _ => println!("Default case, x = {:?}", x), + } + + println!("at the end: x = {:?}, y = {:?}", x, y); +} +``` + +## Multiple Patterns + +``` rust +fn main() { + let x = 1; + + match x { + 1 | 2 => println!("one or two"), + 3 => println!("three"), + _ => println!("anything"), + } +} +``` + +## Matching Ranges of Values with ..= + +``` rust +fn main() { + let x = 5; + + match x { + 1..=5 => println!("one through five"), + _ => println!("something else"), + } +} +``` + +``` rust +fn main() { + let x = 'c'; + + match x { + 'a'..='j' => println!("early ASCII letter"), + 'k'..='z' => println!("late ASCII letter"), + _ => println!("something else"), + } +} +``` + +## Destructuring + +### Destructuring to break apart Values + +1. Destructuring Structs + + ``` rust + struct Point { + x: i32, + y: i32, + } + + fn main() { + let p = Point { x: 0, y: 7 }; + + let Point { x: a, y: b } = p; + assert_eq!(0, a); + assert_eq!(7, b); + } + ``` + + 1. Shorthand version + + ``` rust + struct Point { + x: i32, + y: i32, + } + + fn main() { + let p = Point { x: 0, y: 7 }; + + let Point { x, y } = p; + assert_eq!(0, x); + assert_eq!(7, y); + } + ``` + + ```{=org} + #+RESULTS: + ``` + +### Destructuring and matching literal values in one pattern + +``` rust +struct Point { + x: i32, + y: i32, +} + +fn main() { + let p = Point { x: 0, y: 7 }; + + match p { + Point { x, y: 0 } => println!("On the x axis at {}", x), + Point { x: 0, y } => println!("On the y axis at {}", y), + Point { x, y } => println!("On neither axis: ({}, {})", x, y), + } +} +``` + +### Destructuring Enums + +[Enums](20200902150714-enums) can also be deconstructed: + +``` rust +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(i32, i32, i32), +} + +fn main() { + let msg = Message::ChangeColor(0, 160, 255); + + match msg { + Message::Quit => println!("The Quit variant has no data to destructure."), + Message::Move { x, y } => { + println!("Move in the x direction {} and in the y direction {}", x, y); + } + Message::Write(text) => println!("Text message: {}", text), + Message::ChangeColor(r, g, b) => { + println!("Change the color to red {}, green {}, and blue {}", r, g, b) + } + } +} +``` + +### Destructuring nested Structs and Enums + +Nested [structs](20200831193417-structs) and +[enums](20200902150714-enums) can also be destructured: + +``` rust +enum Color { + Rgb(i32, i32, i32), + Hsv(i32, i32, i32), +} + +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(Color), +} + +fn main() { + let msg = Message::ChangeColor(Color::Hsv(0, 160, 255)); + + match msg { + Message::ChangeColor(Color::Rgb(r, g, b)) => { + println!("Change the color to red {}, green {}, and blue {}", r, g, b) + } + Message::ChangeColor(Color::Hsv(h, s, v)) => println!( + "Change the color to hue {}, saturation {}, and value {}", + h, s, v + ), + _ => (), + } +} +``` + +### Destructuring Structs and Tuples + +``` rust +fn main() { + struct Point { + x: i32, + y: i32, + } + + let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 }); +} +``` + +## Ignoring Values in a Pattern + +### \_ + +1. Ignoring an entire Value with \_ + + ``` rust + fn foo(_: i32, y: i32) { + println!("This code only uses the y parameter: {}", y); + } + + fn main() { + foo(3, 4); + } + ``` + +2. Ignoring parts of a Value with a nested \_ + + ``` rust + fn main() { + let mut setting_value = Some(5); + let new_setting_value = Some(10); + + match (setting_value, new_setting_value) { + (Some(_), Some(_)) => { + println!("Can't overwrite an existing customized value"); + } + _ => { + setting_value = new_setting_value; + } + } + + println!("setting is {:?}", setting_value); + } + ``` + + ``` rust + fn main() { + let numbers = (2, 4, 8, 16, 32); + + match numbers { + (first, _, third, _, fifth) => println!("Some numbers: {}, {}, {}", first, third, fifth), + } + } + ``` + +3. Ignoring an unused Variable by starting its name with \_ + + ``` rust + fn main() { + let _x = 5; + } + ``` + + ```{=org} + #+RESULTS: + ``` + +### … + +1. Ignoring remaining parts of a Value with … + + ``` rust + fn main() { + struct Point { + x: i32, + y: i32, + z: i32, + } + + let origin = Point { x: 0, y: 0, z: 0 }; + + match origin { + Point { x, .. } => println!("x is {}", x), + } + } + ``` + + ``` rust + fn main() { + let numbers = (2, 4, 8, 16, 32); + + match numbers { + (first, .., last) => { + println!("Some numbers: {}, {}", first, last); + } + } + } + ``` + +## Extra conditionals with Match Guards + +``` rust +fn main() { + let num = Some(4); + + match num { + Some(x) if x < 5 => println!("less than five: {}", x), + Some(x) => println!("{}", x), + None => (), + } +} +``` + +``` rust +fn main() { + let x = Some(5); + let y = 10; + + match x { + Some(50) => println!("Got 50"), + Some(n) if n == y => println!("Matched, n = {}", n), + _ => println!("Default case, x = {:?}", x), + } + + println!("at the end: x = {:?}, y = {}", x, y); +} +``` + +``` rust +fn main() { + let x = 4; + let y = false; + + match x { + 4 | 5 | 6 if y => println!("yes"), + _ => println!("no"), + } +} +``` + +## @ Bindings + +``` rust +fn main() { + enum Message { + Hello { id: i32 }, + } + + let msg = Message::Hello { id: 5 }; + + match msg { + Message::Hello { + id: id_variable @ 3..=7, + } => println!("Found an id in range: {}", id_variable), + Message::Hello { id: 10..=12 } => println!("Found an id in another range"), + Message::Hello { id } => println!("Found some other id: {}", id), + } +} +``` diff --git a/content/wiki/20201006111125-javascript_function_declerations.md b/content/wiki/20201006111125-javascript_function_declerations.md new file mode 100644 index 0000000..876ea65 --- /dev/null +++ b/content/wiki/20201006111125-javascript_function_declerations.md @@ -0,0 +1,33 @@ +--- +date: 2020-10-06 +id: 0e8d8e26-e36d-48b6-a333-9c0fbd07b7b0 +title: JavaScript function declarations +--- + +``` javascript +const square = function(x) { + return x * x; +} + +console.log(square(12)) +``` + +``` javascript +const makeNoise = function() { + console.log("Pling!") +} + +makeNoise() +``` + +``` javascript +const power = function(base, exponent) { + let result = 1; + for (let count = 0; count < exponent; count++) { + result *= base; + } + return result; +}; + +console.log(power(2, 10)) +``` diff --git a/content/wiki/20201006111244-declaration_notation.md b/content/wiki/20201006111244-declaration_notation.md new file mode 100644 index 0000000..f077141 --- /dev/null +++ b/content/wiki/20201006111244-declaration_notation.md @@ -0,0 +1,28 @@ +--- +date: 2020-10-06 +id: 2b93c1c4-b0ed-4b03-846b-557ccc9d6080 +title: JavaScript declaration notation +--- + +There is a shorter way to declare functions: + +``` javascript +function square(x) { + return x * x +} + +console.log(square(5)) +``` + +Function declarations are not part of the regular top-to-bottom flow on +control. They are conceptually moved to the top of their scope and can +be used by all the code in that scope. + +``` javascript +console.log("The future says:", future()) + +function future() { + return "Where are my flying cars?" +} + +``` diff --git a/content/wiki/20201006111349-arrow_functions.md b/content/wiki/20201006111349-arrow_functions.md new file mode 100644 index 0000000..ddfd3a2 --- /dev/null +++ b/content/wiki/20201006111349-arrow_functions.md @@ -0,0 +1,41 @@ +--- +date: 2020-10-06 +id: 4851138e-ddbd-4801-8178-51d990e327e5 +title: JavaScript arrow functions +--- + +# Introduction + +``` javascript +const power = (base, exponent) => { + let result = 1; + for (let count = 0; count < exponent; count++) { + result *= base; + } + return result; +}; + +console.log(power(2, 3)) +``` + +If there is only one parameter name, parentheses can be omitted around +the parameter list. Same for the function body and brackets + +``` javascript +const square1 = (x) => { return x * x; }; +const square2 = x => x * x; + +console.log(square1(5)) +console.log(square1(6)) +``` + +When an arrow function has no parameters at all, its parameter is just +an empty set of parentheses + +``` javascript +const horn = () => { + console.log("Toot"); +}; + +horn() +``` diff --git a/content/wiki/20201007093418-javascript_object_getters_setters.md b/content/wiki/20201007093418-javascript_object_getters_setters.md new file mode 100644 index 0000000..6f75f86 --- /dev/null +++ b/content/wiki/20201007093418-javascript_object_getters_setters.md @@ -0,0 +1,22 @@ +--- +date: 2020-10-07 +id: 94a1d579-bd29-42f0-a6c6-2aa0700703d4 +title: JavaScript object getters & setters +--- + +# Example + +``` javascript +const obj = { + get foo() { + console.log('GET foo'); + return 123; + }, + set bar(value) { + console.log('SET bar to '+value); + } +}; + +obj.foo +obj.bar = 'tralala' +``` diff --git a/content/wiki/20201007095614-typescript_never_type.md b/content/wiki/20201007095614-typescript_never_type.md new file mode 100644 index 0000000..8c58a17 --- /dev/null +++ b/content/wiki/20201007095614-typescript_never_type.md @@ -0,0 +1,32 @@ +--- +date: 2020-10-07 +id: 85c2204d-dc1e-4038-9355-8bed1cb4574b +title: TypeScript Never Type +--- + +# Introduction + +[TypeScript](20200929161126-typescript) supports bottom types[^1]. Cases +where this occurs: + +- A function never returns (e.g. if the function body has + `while(true){`}) +- A function always throws + (`function foo(){throw new Error('Not Implemented')`}) + +# Syntax + +``` typescript +let foo: never; // Okay +``` + +``` typescript +let foo: never = 123; // Error: Type number is not assignable to never + +// Okay as the function's return type is `never` +let bar: never = (() => { throw new Error(`Throw my hands in the air like I just don't care`) })(); +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201007101133-typescript_discriminated_union.md b/content/wiki/20201007101133-typescript_discriminated_union.md new file mode 100644 index 0000000..a7a9fc2 --- /dev/null +++ b/content/wiki/20201007101133-typescript_discriminated_union.md @@ -0,0 +1,177 @@ +--- +date: 2020-10-07 +id: e39eaedb-0e83-430a-a7c4-85bb6f89da77 +title: TypeScript Discriminated Union +--- + +# Description + +If your [class](20201009104411-typescript_classes) has a [literal +member](20201002103357-typescript_literal_types) then you can use that +property to discriminate between +[union](20200929163219-typescript_union_type) members. + +# Examples + +``` typescript +interface Square { + kind: "square"; + size: number; +} + +interface Rectangle { + kind: "rectangle"; + width: number; + height: number; +} +type Shape = Square | Rectangle; + +function area(s: Shape) { + if (s.kind === "square") { + // Now TypeScript *knows* that `s` must be a square ;) + // So you can use its members safely :) + return s.size * s.size; + } + else { + // Wasn't a square? So TypeScript will figure out that it must be a Rectangle ;) + // So you can use its members safely :) + return s.width * s.height; + } +} +``` + +## Exhaustive Checks + +Quite commonly you want to make sure that all members of a +[union](20200929163219-typescript_union_type) have some code(action) +against them. You can do that by simply adding a fall through and making +sure that the inferred type in that block is compatible with the +[never](20201007095614-typescript_never_type) type. For example if you +add the exhaustive check you get a nice error: + +``` typescript +interface Square { + kind: "square"; + size: number; +} + +interface Rectangle { + kind: "rectangle"; + width: number; + height: number; +} + +// Someone just added this new `Circle` Type +// We would like to let TypeScript give an error at any place that *needs* to cater for this +interface Circle { + kind: "circle"; + radius: number; +} + +type Shape = Square | Rectangle | Circle; + +function area(s: Shape) { + if (s.kind === "square") { + return s.size * s.size; + } + else if (s.kind === "rectangle") { + return s.width * s.height; + } + else if (s.kind === "circle") { + return Math.PI * (s.radius **2); + } + else { + // Okay once more + const _exhaustiveCheck: never = s; + } +} +``` + +### Switch + +This can also be accomplished with a `switch` statement: + +``` typescript +function area(s: Shape) { + switch (s.kind) { + case "square": return s.size * s.size; + case "rectangle": return s.width * s.height; + case "circle": return Math.PI * s.radius * s.radius; + default: const _exhaustiveCheck: never = s; + } +} +``` + +### Exhaustive checks + +Another solution is to write a function that only accepts a +[never](20201007095614-typescript_never_type) and then throws an +[error](20200901105237-error_handling) if its body every executes: + +``` typescript +function assertNever(x:never): never { + throw new Error('Unexpected value. Should have been never.'); +} + +interface Square { + kind: "square"; + size: number; +} +interface Rectangle { + kind: "rectangle"; + width: number; + height: number; +} +type Shape = Square | Rectangle; + +function area(s: Shape) { + switch (s.kind) { + case "square": return s.size * s.size; + case "rectangle": return s.width * s.height; + // If a new case is added at compile time you will get a compile error + // If a new value appears at runtime you will get a runtime error + default: return assertNever(s); + } +} +``` + +## Retrospective Versioning + +And after you have a bunch of DTOs you realize that name was a poor +choice. You can add versioning retrospectively by creating a new +[union](20200929163219-typescript_union_type) with +[literal](20201002103357-typescript_literal_types) number (or string if +you want) of DTO. Mark the version 0 as undefined and if you have +strictNullChecks enabled it will just work out: + +``` typescript +type DTO = +| { + version: undefined, // version 0 + name: string, + } +| { + version: 1, + firstName: string, + lastName: string, +} +// Even later +| { + version: 2, + firstName: string, + middleName: string, + lastName: string, +} + +function printDTO(dto:DTO) { + if (dto.version == null) { + console.log(dto.name); + } else if (dto.version == 1) { + console.log(dto.firstName,dto.lastName); + } else if (dto.version == 2) { + console.log(dto.firstName, dto.middleName, dto.lastName); + } else { + const _exhaustiveCheck: never = dto; + } +} +``` diff --git a/content/wiki/20201008090316-class_notation.md b/content/wiki/20201008090316-class_notation.md new file mode 100644 index 0000000..ccb39cb --- /dev/null +++ b/content/wiki/20201008090316-class_notation.md @@ -0,0 +1,38 @@ +--- +date: 2020-10-08 +id: 7a97acf5-38db-40c9-b714-4293d88aa113 +title: JavaScript Class Notation +--- + +# Introduction + +By convention, the names of constructors are capitalized so that they +can easily be distinguished from other functions. Thanks to [ECMAScript +2015](https://ecma-international.org/ecma-262/6.0/) above can be +achieved with a saner notation: + +# Example + +``` javascript +class Rabbit { + constructor(type) { + this.type = type; + } + speak(line) { + console.log(`The ${this.type} rabbit says '${line}'`); + } +} + +let killerRabbit = new Rabbit("killer"); +let blackRabbit = new Rabbit("black"); + +killerRabbit.speak("I want blood!"); +blackRabbit.speak("For some reason I appreciate Tyler Perry movies"); +``` + +If one **must** one can also use `class` in expressions: + +``` javascript +let object = new class { getWord() { return "hello"; } }; +console.log(object.getWord()); +``` diff --git a/content/wiki/20201008090449-method_definition.md b/content/wiki/20201008090449-method_definition.md new file mode 100644 index 0000000..6a1f1f1 --- /dev/null +++ b/content/wiki/20201008090449-method_definition.md @@ -0,0 +1,17 @@ +--- +date: 2020-10-08 +id: b7da7f6f-eb57-4303-bdcb-45397afbf5dc +title: JavaScript Classes Method Definition +--- + +# Example + +``` javascript +const obj = { + foo() { + }, + bar() { + this.foo(); + }, +} +``` diff --git a/content/wiki/20201008090613-inheritance.md b/content/wiki/20201008090613-inheritance.md new file mode 100644 index 0000000..b198e7a --- /dev/null +++ b/content/wiki/20201008090613-inheritance.md @@ -0,0 +1,39 @@ +--- +date: 2020-10-08 +id: 3b88db70-6291-45e3-96da-3fb70a43222a +title: JavaScript Class Inheritance +--- + +# Example + +Classes in JavaScript can inherit from each other + +``` javascript +class Parent { + constructor(name, parentChild = "Parent") { + this.parentChild = parentChild + this.name = name + } + + speak(line) { + console.log(`${this.parentChild} ${this.name} says '${line}'`) + } +} + +class Child extends Parent { + constructor(name){ + super(name, "Child") + } +} + +let parent = new Parent("Father"); +let child = new Child("Gregory"); +parent.speak("Get off my lawn!"); +child.speak("Make me old man!"); +``` + +The use of the word `extends` indicates that this class shouldn’t be +directly based on the default [Object](20200826201605-objects) prototype +but on some other class. This is called the superclass. The derived +class is the subclass. The superclass's constructor and methods can be +called by appending `super` in front. diff --git a/content/wiki/20201008092225-index_signatures.md b/content/wiki/20201008092225-index_signatures.md new file mode 100644 index 0000000..cdf9def --- /dev/null +++ b/content/wiki/20201008092225-index_signatures.md @@ -0,0 +1,113 @@ +--- +date: 2020-10-08 +id: a4bfc39c-bfe0-48f0-b58d-6dc473aa8993 +title: TypeScript Index Signatures +--- + +# Introduction + +An [object](20200826201605-objects) in +[JavaScript](20200613170905-javascript) can be accessed with a string to +hold a reference to any other JavaScript object. + +``` typescript +let foo: any = {}; +foo['Hello'] = 'World'; +console.log(foo['Hello']); // World +``` + +``` typescript +class Foo { + constructor(public message: string){}; + log(){ + console.log(this.message) + } +} + +let foo: any = {}; +foo['Hello'] = new Foo('World'); +foo['Hello'].log(); // World +``` + +``` typescript +let obj = { + toString(){ + console.log('toString called') + return 'Hello' + } +} + +let foo: any = {}; +foo[obj] = 'World'; // toString called +console.log(foo[obj]); // toString called, World +console.log(foo['Hello']); // World +``` + +# Syntax + +## Declaring an index signature + +``` typescript +let foo:{ [index:string] : {message: string} } = {}; + +/** + * Must store stuff that conforms to the structure + */ +/** Ok */ +foo['a'] = { message: 'some message' }; +/** Error: must contain a `message` of type string. You have a typo in `message` */ +foo['a'] = { messages: 'some message' }; + +/** + * Stuff that is read is also type checked + */ +/** Ok */ +foo['a'].message; +/** Error: messages does not exist. You have a typo in `message` */ +foo['a'].messages; +``` + +## Interfaces + +As soon as you have a string index signature, all explicit members must +also conform to that index signature. A few +[Interface](20200929162220-interfaces) examples: + +``` typescript +interface Foo { + x: number; +} +let foo: Foo = {x:1,y:2}; +​ +// Directly +foo['x']; // number +​ +// Indirectly +let x = 'x' +foo[x]; // number +``` + +## String literals + +[String Literals](20201002103357-typescript_literal_types) can also be +used in the declaration: + +``` typescript +type Index = 'a' | 'b' | 'c' +type FromIndex = { [k in Index]?: number } + +const good: FromIndex = {b:1, c:2} + +// Error: +// Type '{ b: number; c: number; d: number; }' is not assignable to type 'FromIndex'. +// Object literal may only specify known properties, and 'd' does not exist in type 'FromIndex'. +const bad: FromIndex = {b:1, c:2, d:3}; +``` + +## Generics + +[Generics](20200929163051-typescript_generics) can also be used: + +``` typescript +type FromSomeIndex = { [key in K]: number } +``` diff --git a/content/wiki/20201009090331-javascript_array_methods.md b/content/wiki/20201009090331-javascript_array_methods.md new file mode 100644 index 0000000..9d257dd --- /dev/null +++ b/content/wiki/20201009090331-javascript_array_methods.md @@ -0,0 +1,108 @@ +--- +date: 2020-10-09 +id: c76b3766-a1ed-43f9-bdb6-4076e6bb5b7a +title: JavaScript Array Methods +--- + +# ES6 + +## Static Array methods + +### Array.from() + +``` javascript +const arr2 = Array.from(arguments); // ES6 +``` + +If a value is [iterable](20201014092625-javascript_iterables) (as all +Array-like DOM data structure are by now), you can also use the +[spread](20201014094144-spread) operator (…) to convert it to an +[Array](20200826201029-arrays): + +``` javascript +const arr1 = [...'abc']; + // ['a', 'b', 'c'] +const arr2 = [...new Set().add('a').add('b')]; + // ['a', 'b'] +``` + +### Array.of() + +This returns an array of the passed parameters + +``` javascript +console.log(Array.of(1, 2, 3, 4)) // [1, 2, 3, 4] +``` + +## Array.prototype methods + +### Array.prototype.fill() + +``` javascript +const arr2 = new Array(2).fill(undefined); + // [undefined, undefined] +``` + +### Array.prototype.copyWithin() + +The method signature is: + +``` typescript +Array.prototype.copyWithin(target : number, + start : number, end = this.length) : This +``` + +It copies the elements whose indices are in the range \[start,end) to +index target and subsequent indices. If the two index ranges overlap, +care is taken that all source elements are copied before they are +overwritten. I am confused as to how this is in any way useful. + +``` javascript +const arr = [0,1,2,3]; +console.log(arr.copyWithin(2, 0, 2)) // [0, 1, 0, 1] +``` + +### Searching for elements + +1. Array.prototype.findIndex() + + ``` javascript + console.log([6, -6, 8].findIndex(x => x < 0)) // 1 + ``` + +2. Array.prototype.find() + + ``` javascript + console.log([6, -6, 8].find(x => x < 0)) // -6 + ``` + +### Iteration + +1. Array.prototype.entries() + + ``` javascript + console.log(Array.from(['a', 'b'].entries())) // [ [ 0, 'a' ], [ 1, 'b' ] ] + ``` + +2. Array.prototype.values() + + ``` javascript + console.log(Array.from(['a', 'b'].values())) // ['a', 'b'] + ``` + +3. Array.prototype.keys() + + ``` javascript + console.log(Array.from(['a', 'b'].keys())) // [0, 1] + ``` + +# ES2016 + +## Array.prototype.includes() + +Tells you if array includes a certain element: + +``` javascript +console.log(["a", "b", "c"].includes("a")); // true +console.log(["a", "b", "c"].includes("d")); // false +``` diff --git a/content/wiki/20201009090331-javascript_array_prototype_methods.md b/content/wiki/20201009090331-javascript_array_prototype_methods.md new file mode 100644 index 0000000..edd9cd4 --- /dev/null +++ b/content/wiki/20201009090331-javascript_array_prototype_methods.md @@ -0,0 +1,26 @@ +--- +date: 2020-10-09 +id: 6c19156b-877a-4109-95ea-66e1f10d8385 +title: JavaScript Array Prototype Methods +--- + +- [Array.prototype.copyWithin()](20201113104240-array_prototype_copywithin) +- [Array.prototype.fill()](20201113104217-array_prototype_fill) +- [Array.prototype.includes()](20201113105707-array_prototype_includes) +- [Array.prototype.map()](20201113113141-array_prototype_map) +- [Array.prototype.Sort()](20201116155459-array_prototype_sort) + +# Search + +- [Array Search Prototype + Methods](20201113104552-array_search_prototype_methods) + +# Iteration + +- [Array Iteration Prototype + Methods](20201113104619-array_iteration_prototype_methods) + +# Flatteners + +- [Array.prototype.flat()](20201113112029-array_prototype_flat) +- [Array.prototype.flatMap()](20201113112058-array_prototype_flatmap) diff --git a/content/wiki/20201009104050-typescript_4_0.md b/content/wiki/20201009104050-typescript_4_0.md new file mode 100644 index 0000000..e3640d8 --- /dev/null +++ b/content/wiki/20201009104050-typescript_4_0.md @@ -0,0 +1,9 @@ +--- +date: 2020-10-09 +id: 606ce4c6-7e92-499c-8a94-19bbc93b2b3c +title: TypeScript 4.0 +--- + +- [TypeScript Tuple Type](20200929163624-typescript_tuple_type) +- [TypeScript Functions](20201001110806-typescript_functions) +- [TypeScript Classes](20201009104411-typescript_classes) diff --git a/content/wiki/20201009104411-typescript_classes.md b/content/wiki/20201009104411-typescript_classes.md new file mode 100644 index 0000000..fd81cd1 --- /dev/null +++ b/content/wiki/20201009104411-typescript_classes.md @@ -0,0 +1,27 @@ +--- +date: 2020-10-09 +id: b6fa7fa7-644f-42ab-bee6-71f4f58a60f2 +title: TypeScript Classes +--- + +# TypeScript 4.0 + +## Class Property Inference from Constructors + +TypeScript 4.0 can now use control flow analysis to determine the types +of properties in [classes](20201008090316-class_notation) when +noImplicitAny is enabled. + +``` typescript +class Square { + // Previously: implicit any! + // Now: inferred to `number`! + area; + sideLength; + + constructor(sideLength: number) { + this.sideLength = sideLength; + this.area = sideLength ** 2; + } +} +``` diff --git a/content/wiki/20201012093745-javascript_maps.md b/content/wiki/20201012093745-javascript_maps.md new file mode 100644 index 0000000..c914013 --- /dev/null +++ b/content/wiki/20201012093745-javascript_maps.md @@ -0,0 +1,97 @@ +--- +date: 2020-10-12 +id: 0ad60ce3-4e34-490e-a565-a0ce330e6fc8 +title: JavaScript Maps +--- + +# Description + +For sane people [ES6](20201030093404-es6) comes with a half assed +"solution" handy data structure called `Map` which prevents the diy +shenanigans below. + +# Syntax + +## Basic operation + +### Single entries + +``` javascript +const map = new Map(); +const KEY = {}; + +map.set(KEY, 123); +console.log(map.get(KEY)); // 123 + +console.log(map.has(KEY)); // true + +map.delete(KEY); +console.log(map.has(KEY)); // false +``` + +### Array + +``` javascript +const map = new Map([ + [ 1, 'one' ], + [ 2, 'two' ], + [ 3, 'three' ], +]); +``` + +## Iteration + +### Keys + +``` javascript +const map = new Map([ + [false, 'no'], + [true, 'yes'], +]); + +for (const key of map.keys()) { + console.log(key); +} +``` + +### Values + +``` javascript +const map = new Map([ + [false, 'no'], + [true, 'yes'], +]); + +for (const value of map.values()) { + console.log(value); +} +``` + +### Entries + +``` javascript +const map = new Map([ + [false, "no"], + [true, "yes"], +]); + +for (const entry of map.entries()) { + console.log(entry[0], entry[1]); +} +``` + +### Converting to Arrays + +The [spread](20201014094144-spread) operator (…) can turn an +[iterable](20201014092625-javascript_iterables) into an +[Array](20200826201029-arrays) + +``` javascript +const map = new Map().set(false, 'no').set(true, 'yes'); +console.log([...map.keys()]) // false, true +``` + +``` javascript +const map = new Map().set(false, 'no').set(true, 'yes'); +console.log([...map]) +``` diff --git a/content/wiki/20201012094248-javascript_sets.md b/content/wiki/20201012094248-javascript_sets.md new file mode 100644 index 0000000..6439297 --- /dev/null +++ b/content/wiki/20201012094248-javascript_sets.md @@ -0,0 +1,18 @@ +--- +date: 2020-10-12 +id: ee9a4791-e3e8-4437-98fa-6c2d34be1a8e +title: JavaScript Sets +--- + +# Introduction + +A +[Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) +is a collection of unique elements. + +# Example + +``` javascript +const arr = [5, 1, 5, 7, 7, 5]; +const unique = [...new Set(arr)]; // [ 5, 1, 7 ] +``` diff --git a/content/wiki/20201012094749-javascript_weakmaps.md b/content/wiki/20201012094749-javascript_weakmaps.md new file mode 100644 index 0000000..3bdc0a4 --- /dev/null +++ b/content/wiki/20201012094749-javascript_weakmaps.md @@ -0,0 +1,46 @@ +--- +date: 2020-10-12 +id: e06279b3-4488-40b1-b822-fca19b47089a +title: JavaScript WeakMaps +--- + +# Introduction + +A WeakMap is a [Map](20201012093745-javascript_maps) that doesn’t +prevent its keys from being garbage-collected. That means that you can +associate data with [objects](20200826201605-objects) without having to +worry about memory leaks. + +# Example + +``` javascript +//----- Manage listeners + +const _objToListeners = new WeakMap(); + +function addListener(obj, listener) { + if (! _objToListeners.has(obj)) { + _objToListeners.set(obj, new Set()); + } + _objToListeners.get(obj).add(listener); +} + +function triggerListeners(obj) { + const listeners = _objToListeners.get(obj); + if (listeners) { + for (const listener of listeners) { + listener(); + } + } +} + +//----- Example: attach listeners to an object + +const obj = {}; +addListener(obj, () => console.log('hello')); +addListener(obj, () => console.log('world')); + +//----- Example: trigger listeners + +triggerListeners(obj); +``` diff --git a/content/wiki/20201014092625-javascript_iterables.md b/content/wiki/20201014092625-javascript_iterables.md new file mode 100644 index 0000000..5fea98a --- /dev/null +++ b/content/wiki/20201014092625-javascript_iterables.md @@ -0,0 +1,26 @@ +--- +date: 2020-10-14 +id: f1c572d5-868b-4ce0-b1ac-9f7cc32dae3d +title: JavaScript Iterables +--- + +# Introduction + +An *iterable* is a data structure that wants to make its elements +accessible to the public. It does so by implementing a method whose key +is +[Symbol.iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator). +That method is a factory for +[iterators](20201014092846-javascript_iterator). + +# Iterable values + +- [Arrays](20200826201029-arrays) +- [Strings](20200922164551-strings) +- [Maps](20201012093745-javascript_maps) +- [Sets](20201012094248-javascript_sets) +- DOM data structures + +# See also + +- [Destructuring Iterables](20201103112001-destructuring_iterables) diff --git a/content/wiki/20201014092846-javascript_iterator.md b/content/wiki/20201014092846-javascript_iterator.md new file mode 100644 index 0000000..4c7b36f --- /dev/null +++ b/content/wiki/20201014092846-javascript_iterator.md @@ -0,0 +1,41 @@ +--- +date: 2020-10-14 +id: 9f77a5b0-a06d-46d0-828e-d6c5fe33111d +title: JavaScript Iterator +--- + +# Introduction + +An *iterator* is a pointer for traversing the elements of a data +structure. + +# Examples + +## Syntax + +``` javascript +const iterable = ["a", "b"]; +const iterator = iterable[Symbol.iterator](); + +console.log(iterator.next()); // { value: 'a', done: false } +console.log(iterator.next()); // { value: 'b', done: false } +console.log(iterator.next()); // { value: undefined, done: true } +``` + +## TypeScript Interfaces + +Expressed as [interfaces](20200929162220-interfaces) in +[TypeScript](20200929161126-typescript) notation: + +``` typescript +interface Iterable { + [Symbol.iterator]() : Iterator; +} +interface Iterator { + next() : IteratorResult; +} +interface IteratorResult { + value: any; + done: boolean; +} +``` diff --git a/content/wiki/20201014094144-spread.md b/content/wiki/20201014094144-spread.md new file mode 100644 index 0000000..8d18e89 --- /dev/null +++ b/content/wiki/20201014094144-spread.md @@ -0,0 +1,29 @@ +--- +date: 2020-10-14 +id: 981a83a9-9288-400b-a9d7-0f28a3795495 +title: Spread (…) +--- + +# Examples + +Math.max() returns the numerically greatest of its arguments. It works +for an arbitrary number of arguments, but not for Arrays. + +``` javascript +console.log(Math.max(...[-1, 5, 11, 3])) +``` + +``` javascript +const arr1 = ['a', 'b']; +const arr2 = ['c', 'd']; + +arr1.push(...arr2); // arr1 is now ['a', 'b', 'c', 'd'] +``` + +``` javascript +const arr1 = ['a', 'b']; +const arr2 = ['c']; +const arr3 = ['d', 'e']; + +console.log([...arr1, ...arr2, ...arr3]); // [ 'a', 'b', 'c', 'd', 'e' ] +``` diff --git a/content/wiki/20201021141613-vue_js.md b/content/wiki/20201021141613-vue_js.md new file mode 100644 index 0000000..b8a5db3 --- /dev/null +++ b/content/wiki/20201021141613-vue_js.md @@ -0,0 +1,13 @@ +--- +date: 2020-10-21 +id: b1c3aaf5-d35c-4549-a39a-dd43f6b42c37 +title: Vue.js +--- + +# Handy links + +- Vue Test Utils[^1] + +# Footnotes + +[^1]: diff --git a/content/wiki/20201022094207-javascript_proxies.md b/content/wiki/20201022094207-javascript_proxies.md new file mode 100644 index 0000000..3d914b9 --- /dev/null +++ b/content/wiki/20201022094207-javascript_proxies.md @@ -0,0 +1,312 @@ +--- +date: 2020-10-22 +id: c5010eb1-4ce2-4415-8421-7710daecad0a +title: JavaScript Proxies +--- + +# Introduction + +ECMAScript 6 proxies bring intercession to +[JavaScript](20200613170905-javascript). They work as follows. There are +many operations that you can perform on an +[object](20200826201605-objects) obj. For example: + +- Getting the property `prop` of an object `obj` (`obj.prop`) +- Checking whether an object `obj` has a property `prop` + (`'prop' in obj`) + +Proxies are special objects that allow you customize some of these +operations. A proxy is created with two parameters: + +- `handler`: For each operation, there is a corresponding handler + method that – if present – performs that operation. Such a method + *intercepts* the operation (on its way to the target) and is called + a *trap* (a term borrowed from the domain of operating systems). +- `target`: If the handler doesn’t intercept an operation then it is + performed on the target. That is, it acts as a fallback for the + handler. In a way, the proxy wraps the target. + +# Examples + +In the following example the handler intercepts the operations `get` and +`has`: + +``` javascript +const target = {}; +const handler = { + /** Intercepts: getting properties */ + get(target, propKey, receiver) { + console.log(`GET ${propKey}`); + return 123; + }, + + /** Intercepts: checking whether properties exist */ + has(target, propKey) { + console.log(`HAS ${propKey}`); + return true; + }, +}; +const proxy = new Proxy(target, handler); + +console.log(proxy.foo); // 123 +console.log("hello" in proxy); // true + +proxy.bar = "abc"; +console.log(target.bar); // "abc" +``` + +# Use cases for proxies + +## Tracing property acesses (get, set) + +``` javascript +function tracePropAccess(obj, propKeys) { + const propKeySet = new Set(propKeys); + return new Proxy(obj, { + get(target, propKey, receiver) { + if (propKeySet.has(propKey)) { + console.log("GET " + propKey); + } + return Reflect.get(target, propKey, receiver); + }, + set(target, propKey, value, receiver) { + if (propKeySet.has(propKey)) { + console.log("SET " + propKey + "=" + value); + } + return Reflect.set(target, propKey, value, receiver); + }, + }); +} + +class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } + toString() { + return `Point(${this.x}, ${this.y})`; + } +} +// Trace accesses to properties `x` and `y` +let p = new Point(5, 7); +p = tracePropAccess(p, ["x", "y"]); + +// GET x +// 4 +console.log(p.x); + +// SET x=21 +// 21 +console.log((p.x = 21)); + +// GET x +// GET y +// Point(21, 7) +console.log(p.toString()); +``` + +## Warning about unknown properties (get,set) + +When it comes to accessing properties, JavaScript is very forgiving. For +example, if you try to read a property and misspell its name, you don’t +get an exception, you get the result `undefined`. You can use proxies to +get an exception in such a case. This works as follows. We make the +proxy a prototype of an object. + +If a property isn’t found in the object, the `get` trap of the proxy is +triggered. If the property doesn’t even exist in the prototype chain +after the proxy, it really is missing and we throw an exception. +Otherwise, we return the value of the inherited property. We do so by +forwarding the `get` operation to the target (the prototype of the +target is also the prototype of the proxy). + +### Unknown Property Examples + +1. Object + + ``` javascript + const PropertyChecker = new Proxy( + {}, + { + get(target, propKey, receiver) { + if (!(propKey in target)) { + throw new ReferenceError("Unknown property: " + propKey); + } + return Reflect.get(target, propKey, receiver); + }, + } + ); + + const obj = { __proto__: PropertyChecker, foo: 123 }; + // 123 + console.log(obj.foo); + + // ReferenceError: Unknown property: fo + obj.fo + + // [object Object] + obj.toString() + ``` + +2. Class + + If we turn `PropertyChecker` into a constructor, we can use it for + [classes](20201008090316-class_notation) via extends: + + ``` javascript + function PropertyChecker() {} + PropertyChecker.prototype = new Proxy(/*···*/); + + class Point extends PropertyChecker { + constructor(x, y) { + super(); + this.x = x; + this.y = y; + } + } + + const p = new Point(5, 7); + console.log(p.x); // 5 + console.log(p.z); // ReferenceError + ``` + +## Negative Array indices (get) + +Some [array prototype +methods](20201009090331-javascript_array_prototype_methods) let you +refer to the last element via -1, to the second-to-last element via -2, +etc. For example: + +``` javascript +console.log(["a", "b", "c"].slice(-1)); // ['c'] +``` + +Alas, that doesn’t work when accessing elements via the bracket operator +(\[\]). We can, however, use proxies to add that capability. The +following function createArray() creates Arrays that support negative +indices. It does so by wrapping proxies around Array instances. The +proxies intercept the get operation that is triggered by the bracket +operator. + +``` javascript +function createArray(...elements) { + const handler = { + get(target, propKey, receiver) { + // Sloppy way of checking for negative indices + const index = Number(propKey); + if (index < 0) { + propKey = String(target.length + index); + } + return Reflect.get(target, propKey, receiver); + }, + }; + // Wrap a proxy around an Array + const target = []; + target.push(...elements); + return new Proxy(target, handler); +} + +const arr = createArray("a", "b", "c"); +console.log(arr[-1]); // c +``` + +## Data binding (set) + +``` javascript +function createObservedArray(callback) { + const array = []; + return new Proxy(array, { + set(target, propertyKey, value, receiver) { + callback(propertyKey, value); + return Reflect.set(target, propertyKey, value, receiver); + } + }); +} +const observedArray = createObservedArray( + (key, value) => console.log(`${key}=${value}`)); +observedArray.push('a'); + +``` + +## Accessing a restful web service + +``` javascript +function httpGet(url) { + return new Promise((resolve, reject) => { + const request = new XMLHttpRequest(); + Object.assign(request, { + onload() { + if (this.status === 200) { + // Success + resolve(this.response); + } else { + // Something went wrong (404 etc.) + reject(new Error(this.statusText)); + } + }, + onerror() { + reject(new Error("XMLHttpRequest Error: " + this.statusText)); + }, + }); + request.open("GET", url); + request.send(); + }); +} + +function createWebService(baseUrl) { + return new Proxy( + {}, + { + get(target, propKey, receiver) { + // Return the method to be called + return () => httpGet(baseUrl + "/" + propKey); + }, + } + ); +} + +const service = createWebService("http://example.com/data"); +// Read JSON data in http://example.com/data/employees +service.employees().then((json) => { + const employees = JSON.parse(json); +}); +``` + +## Recoverable references + +*Revocable references* work as follows: A client is not allowed to +access an important resource (an object) directly, only via a reference +(an intermediate object, a wrapper around the resource). Normally, every +operation applied to the reference is forwarded to the resource. After +the client is done, the resource is protected by revoking the reference, +by switching it off. Henceforth, applying operations to the reference +throws exceptions and nothing is forwarded, anymore. + +In the following example, we create a revocable reference for a +resource. We then read one of the resource’s properties via the +reference. That works, because the reference grants us access. Next, we +revoke the reference. Now the reference doesn’t let us read the +property, anymore. + +``` javascript +function createRevocableReference(target) { + const handler = {}; // forward everything + const { proxy, revoke } = Proxy.revocable(target, handler); + return { reference: proxy, revoke }; +} + +const resource = { x: 11, y: 8 }; +const { reference, revoke } = createRevocableReference(resource); + +// Access granted +console.log(reference.x); // 11 + +revoke(); + +// Access denied +console.log(reference.x); // TypeError: Revoked +``` + +# See also + +- [Metaprogramming](20201022095438-javascript_metaprogramming) diff --git a/content/wiki/20201022095438-javascript_metaprogramming.md b/content/wiki/20201022095438-javascript_metaprogramming.md new file mode 100644 index 0000000..089f2b3 --- /dev/null +++ b/content/wiki/20201022095438-javascript_metaprogramming.md @@ -0,0 +1,93 @@ +--- +date: 2020-10-22 +id: b866160c-ac93-45af-8faf-1fd40f002f77 +title: JavaScript Metaprogramming +--- + +# Introduction + +In programming, there are levels: + +- At the *base level* (also called: *application level*), code + processes user input. +- At the *meta level*, code processes base level code. + +## Examples + +An example of this is +[eval](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)[^1]: + +``` javascript +console.log(eval("5 + 2")); // 7 +``` + +``` javascript +const obj = { + hello() { + console.log("Hello!"); + }, +}; + +// Meta level +for (const key of Object.keys(obj)) { + console.log(key); +} +``` + +All [Object.\* +methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#) +can be considered metaprogramming functionality + +# Kinds of metaprogramming + +Reflective metaprogramming means that a program processes itself. +Kiczales et al[^2]. \[2\] distinguish three kinds of reflective +metaprogramming: + +- **Introspection:** you have read-only access to the structure of a + program. +- **Self-modification:** you can change that structure +- **Intercession:** you can define the semantics of some language + operations + +## Introspection + +[Object.keys()](20200826201605-objects.org::*Object.keys) performs +introspection + +## self-modification + +The following function `moveProperty` moves a property from a source to +a target. It performs self-modification via the bracket operator for +property access, the assignment operator and the delete operator. (In +production code, you’d probably use property descriptors for this task.) + +``` javascript +function moveProperty(source, propertyName, target) { + target[propertyName] = source[propertyName]; + delete source[propertyName]; +} + +const obj1 = { prop: "abc" }; +const obj2 = {}; +moveProperty(obj1, "prop", obj2); + +console.log(obj1); // {} +console.log(obj2); // { prop: 'abc' } +``` + +## intercession + +ECMAScript 5 doesn't support intercession. +[Proxies](20201022094207-javascript_proxies) were created to fill that +gap. + +# Footnotes + +[^1]: Don't ever use eval. If you think you're a clever clogs that can + work your away around the obvious security issues, then you + especially should not use eval. + +[^2]: "[The Art of the Metaobject + Protocol](http://mitpress.mit.edu/books/art-metaobject-protocol)" by + Gregor Kiczales, Jim des Rivieres and Daniel G. Bobrow. Book, 1991. diff --git a/content/wiki/20201023130243-es2016.md b/content/wiki/20201023130243-es2016.md new file mode 100644 index 0000000..970f8d9 --- /dev/null +++ b/content/wiki/20201023130243-es2016.md @@ -0,0 +1,20 @@ +--- +date: 2020-10-23 +id: e87fde6a-5859-4c13-90bd-342a5ccf602f +title: ES2016 +--- + +# Introduction + +What's new in ES2016. + +# Operators + +- [Exponentation + Operator](20201112110203-javascript_exponentation_operator) + +# Arrays + +## Prototype Methods + +- [Array.prototype.includes()](20201113105707-array_prototype_includes) diff --git a/content/wiki/20201026103714-javascript_async_functions.md b/content/wiki/20201026103714-javascript_async_functions.md new file mode 100644 index 0000000..908246c --- /dev/null +++ b/content/wiki/20201026103714-javascript_async_functions.md @@ -0,0 +1,39 @@ +--- +date: 2020-10-26 +id: 03f42b69-8321-443f-9d1d-fb7814999dd7 +title: JavaScript Async Functions +--- + +# Introduction + +Async Functions[^1] is a new feature implemented in +[ES2017](20201026104538-es2017) to handle +[promises](20200911154351-promises). + +# Syntax + +## Fulfilling a promise + +``` javascript +async function asyncFunc() { + return 123; +} + +asyncFunc().then((x) => console.log(x)); +// 123 +``` + +## Rejecting a promise + +``` javascript +async function asyncFunc() { + throw new Error("Problem!"); +} + +asyncFunc().catch((err) => console.log(err)); +// Error: Problem! +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201026104538-es2017.md b/content/wiki/20201026104538-es2017.md new file mode 100644 index 0000000..c9f760a --- /dev/null +++ b/content/wiki/20201026104538-es2017.md @@ -0,0 +1,46 @@ +--- +date: 2020-10-26 +id: d773822a-2ab2-4661-b5fa-8e16c5fe0dc4 +title: ES2017 +--- + +# Description + +What's new in ES2017 + +# Async functions + +## Fulfilling a [promise](20200911154351-promises) + +``` javascript +async function asyncFunc() { + return 123; +} + +asyncFunc().then((x) => console.log(x)); +// 123 +``` + +## Rejecting a [promise](20200911154351-promises) + +``` javascript +async function asyncFunc() { + throw new Error("Problem!"); +} + +asyncFunc().catch((err) => console.log(err)); +// Error: Problem! +``` + +# Object functions + +- [Object.entries](20201113102048-object_entries) +- [Object.values](20201113102106-object_values) +- [Object.getOwnPropertyDescriptors](20201113102125-object_getownpropertydescriptors) + +# String methods + +Pads the beginning of a [string](20200922164551-strings) + +- [padStart](20201112095657-javascript_string_padstart_method) +- [padEnd](20201112095711-javascript_string_padend_method) diff --git a/content/wiki/20201029194838-carthaginian_peace.md b/content/wiki/20201029194838-carthaginian_peace.md new file mode 100644 index 0000000..8588a81 --- /dev/null +++ b/content/wiki/20201029194838-carthaginian_peace.md @@ -0,0 +1,17 @@ +--- +date: 2020-10-29 +id: 5166162e-b27a-49f2-bbf6-c40891df367b +title: Carthaginian peace +--- + +A Carthaginian peace is the imposition of a very brutal "peace" achieved +by completely crushing the enemy.The term derives from the peace imposed +on [Carthage](https://en.wikipedia.org/wiki/Ancient_Carthage) by +[Rome](https://en.wikipedia.org/wiki/Ancient_Rome). After the [Second +Punic War](https://en.wikipedia.org/wiki/Second_Punic_War), Carthage +lost all its colonies, was forced to demilitarize and pay a constant +tribute to Rome and could enter war only with Rome's permission. At the +end of the [Third Punic +War](https://en.wikipedia.org/wiki/Third_Punic_War),the Romans +systematically burned Carthage to the ground and enslaved its +population. diff --git a/content/wiki/20201029195142-detritus.md b/content/wiki/20201029195142-detritus.md new file mode 100644 index 0000000..08f7fa5 --- /dev/null +++ b/content/wiki/20201029195142-detritus.md @@ -0,0 +1,10 @@ +--- +date: 2020-10-29 +id: 4c55f6c4-9bc7-48aa-bb28-bfaa37ba85a9 +title: detritus +--- + +1. geology : loose material (such as rock fragments or organic + particles) that results directly from disintegration +2. - a product of disintegration, destruction, or wearing away + - miscellaneous remnants diff --git a/content/wiki/20201029195302-useful_idiot.md b/content/wiki/20201029195302-useful_idiot.md new file mode 100644 index 0000000..8c310af --- /dev/null +++ b/content/wiki/20201029195302-useful_idiot.md @@ -0,0 +1,13 @@ +--- +date: 2020-10-29 +id: f4965fea-590f-41d2-ad18-890062a9e6d9 +title: Useful idiot +--- + +In political jargon, a useful idiot is a derogatory term for a person +perceived as propagandizing for a cause without fully comprehending the +cause's goals, and who is cynically used by the cause's leaders. The +term was originally used during the Cold War to describe non-communists +regarded as susceptible to communist propaganda and manipulation. The +term has often been attributed to Vladimir Lenin, but this attribution +is unsubstantiated. diff --git a/content/wiki/20201029195404-intercommunicating_zones.md b/content/wiki/20201029195404-intercommunicating_zones.md new file mode 100644 index 0000000..7ebc7cd --- /dev/null +++ b/content/wiki/20201029195404-intercommunicating_zones.md @@ -0,0 +1,15 @@ +--- +date: 2020-10-29 +id: 9e38c047-00aa-4734-96ed-fc9257e6c19c +title: Intercommunicating zones +--- + +Term coined by Philip D.Curtin[^1]. Geographical areas which primarily +interact internally as opposed towards the outside world. Some examples: + +- China +- The Americas + +# Footnotes + +[^1]: diff --git a/content/wiki/20201029195742-historical_terms.md b/content/wiki/20201029195742-historical_terms.md new file mode 100644 index 0000000..e647b49 --- /dev/null +++ b/content/wiki/20201029195742-historical_terms.md @@ -0,0 +1,9 @@ +--- +date: 2020-10-29 +id: d8d4ec68-d827-43ad-b76f-842d4b1e6848 +title: Historical Terms +--- + +- [bluestocking](20201029201415-bluestocking) +- [Carthaginian peace](20201029194838-carthaginian_peace) +- [Intercommunicating zones](20201029195404-intercommunicating_zones) diff --git a/content/wiki/20201029195945-geographic_terms.md b/content/wiki/20201029195945-geographic_terms.md new file mode 100644 index 0000000..41ce610 --- /dev/null +++ b/content/wiki/20201029195945-geographic_terms.md @@ -0,0 +1,7 @@ +--- +date: 2020-10-29 +id: 2af63cff-05c6-4837-8bb7-b3f421d51f11 +title: Geographic Terms +--- + +- [detritus](20201029195142-detritus) diff --git a/content/wiki/20201029195945-geographical_terms.md b/content/wiki/20201029195945-geographical_terms.md new file mode 100644 index 0000000..6c65e1a --- /dev/null +++ b/content/wiki/20201029195945-geographical_terms.md @@ -0,0 +1,7 @@ +--- +date: 2020-10-29 +id: 4256a7e0-72d4-49d1-a5d9-71f0bd3f7400 +title: Geographical terms +--- + +- [detritus](20201029195142-detritus) diff --git a/content/wiki/20201029200040-political_science_terms.md b/content/wiki/20201029200040-political_science_terms.md new file mode 100644 index 0000000..95d8729 --- /dev/null +++ b/content/wiki/20201029200040-political_science_terms.md @@ -0,0 +1,7 @@ +--- +date: 2020-10-29 +id: 6b7947f5-9261-41cd-b387-9e2c49b84909 +title: Political science terms +--- + +- [Useful idiot](20201029195302-useful_idiot) diff --git a/content/wiki/20201029200235-podophilia.md b/content/wiki/20201029200235-podophilia.md new file mode 100644 index 0000000..cde0f1c --- /dev/null +++ b/content/wiki/20201029200235-podophilia.md @@ -0,0 +1,11 @@ +--- +date: 2020-10-29 +id: 26e9ea5f-2f3c-4f75-9794-e6405e93e4f1 +title: podophilia +--- + +A pronounced sexual interest in feet (or shoes), which is the most +common sexual preference for otherwise non-sexual body parts. For a foot +fetishist, points of attraction include the shape and size of the foot, +toes, toenails, jewelry, treatments (e.g., pedicure), state of dress, +odour, and sensory interaction diff --git a/content/wiki/20201029200327-sexual_terms.md b/content/wiki/20201029200327-sexual_terms.md new file mode 100644 index 0000000..82b0670 --- /dev/null +++ b/content/wiki/20201029200327-sexual_terms.md @@ -0,0 +1,7 @@ +--- +date: 2020-10-29 +id: 7085dfcb-544b-4829-bc0d-d75976caf013 +title: Sexual terms +--- + +- [podophilia](20201029200235-podophilia) diff --git a/content/wiki/20201029201415-bluestocking.md b/content/wiki/20201029201415-bluestocking.md new file mode 100644 index 0000000..339506a --- /dev/null +++ b/content/wiki/20201029201415-bluestocking.md @@ -0,0 +1,11 @@ +--- +date: 2020-10-29 +id: 0b1215e6-ffa0-4ef5-a51a-007b38b80552 +title: bluestocking +--- + +A woman having intellectual or literary interests[^1] + +# Footnotes + +[^1]: diff --git a/content/wiki/20201029204128-gregarious.md b/content/wiki/20201029204128-gregarious.md new file mode 100644 index 0000000..45d2e87 --- /dev/null +++ b/content/wiki/20201029204128-gregarious.md @@ -0,0 +1,7 @@ +--- +date: 2020-10-29 +id: 92e1a107-5fb8-48af-8645-f521ec0fffd4 +title: gregarious +--- + +Fond of company; sociable. diff --git a/content/wiki/20201029204304-adjectives.md b/content/wiki/20201029204304-adjectives.md new file mode 100644 index 0000000..eb87a7d --- /dev/null +++ b/content/wiki/20201029204304-adjectives.md @@ -0,0 +1,16 @@ +--- +date: 2020-10-29 +id: e94a5126-bc69-46fd-88d8-2d76def01f8d +title: Adjectives +--- + +- [antecedent](20201030195742-antecedent) +- [eidetic](20201109124059-eidetic) +- [gregarious](20201029204128-gregarious) +- [imperturbable](20201109121645-imperturbable) +- [inchmeal](20201109124204-inchmeal) +- [indolent](20201116182958-indolent) +- [perfunctory](20201109122833-perfunctory) +- [sanguine](20201109123624-sanguine) +- [tawdry](20220917160601-tawdry) +- [wily](20201109121740-wily) diff --git a/content/wiki/20201030092200-javascript_async_iterator.md b/content/wiki/20201030092200-javascript_async_iterator.md new file mode 100644 index 0000000..37e97cd --- /dev/null +++ b/content/wiki/20201030092200-javascript_async_iterator.md @@ -0,0 +1,57 @@ +--- +date: 2020-10-30 +id: fc8cc294-ab54-44cb-8a3a-f18036ffe175 +title: JavaScript Async Iterator +--- + +# Syntax + +``` javascript +async function* createAsyncIterable(syncIterable) { + for (const elem of syncIterable) { + yield elem; + } +} + +const asyncIterable = createAsyncIterable(["a", "b"]); +const asyncIterator = asyncIterable[Symbol.asyncIterator](); +asyncIterator + .next() + .then((iterResult1) => { + console.log(iterResult1); + return asyncIterator.next(); + // { value: 'a', done: false } + }) + .then((iterResult2) => { + console.log(iterResult2); + return asyncIterator.next(); + // { value: 'b', done: false } + }) + .then((iterResult3) => { + console.log(iterResult3); + // { value: undefined, done: true } + }); +``` + +# TypeScript interfaces + +The [interfaces](20200929162220-interfaces), in +[TypeScript](20200929161126-typescript) notation: + +``` typescript +interface AsyncIterable { + [Symbol.asyncIterator](): AsyncIterator; +} +interface AsyncIterator { + next(): Promise; +} +interface IteratorResult { + value: any; + done: boolean; +} +``` + +# See also + +- [Generators](20200911155947-generators) +- [For Await Of](20201030095741-javascript_for_await_of) diff --git a/content/wiki/20201030093304-javascript_for_of.md b/content/wiki/20201030093304-javascript_for_of.md new file mode 100644 index 0000000..8806b4c --- /dev/null +++ b/content/wiki/20201030093304-javascript_for_of.md @@ -0,0 +1,21 @@ +--- +date: 2020-10-30 +id: 88c7d978-30a1-4908-bbd8-3263fb6c1d44 +title: JavaScript For Of +--- + +# Syntax + +``` javascript +const arr = ['a', 'b', 'c']; +for (const elem of arr) { + console.log(elem); +} +``` + +``` javascript +const arr = ["a", "b", "c"]; +for (const [index, elem] of arr.entries()) { + console.log(index + ". " + elem); +} +``` diff --git a/content/wiki/20201030093404-es6.md b/content/wiki/20201030093404-es6.md new file mode 100644 index 0000000..a8c922e --- /dev/null +++ b/content/wiki/20201030093404-es6.md @@ -0,0 +1,114 @@ +--- +date: 2020-10-30 +id: 157844bd-887b-4871-8e2c-935adc6cc4a1 +title: ES6 +--- + +# Introduction + +What's new in ES6[^1] + +# Control flows + +- [for of](20201030093304-javascript_for_of) + +# Parameters + +- [JavaScript Rest Parameters](20200922162500-rest_parameters) +- [JavaScript Named parameters](20200922162127-named_parameters) + +# Destructuring + +- [Destructuring Arrays](20201103111509-destructuring_arrays) +- [Destructuring Iterables](20201103112001-destructuring_iterables) +- [Destructuring Objects](20201103111746-destructuring_objects) +- [Destructuring Default + Values](20201103113124-destructuring_default_values) + +# Errors + +- [Custom Error Types](20201111093651-javascript_custom_error_types) + +# Strings + +## Methods + +- [endsWith](20201112095428-javascript_string_endswith_method) + +## Literals + +- [String Literals](20201112100548-javascript_string_literals) +- [Tagged Template + Literals](20201112100859-javascript_tagged_template_literals) + +## Escapes + +- [Unicode Code Point + Escapes](20201112101432-unicode_code_point_escapes) + +## Iteration + +- [String Iteration](20201112101851-javascript_string_iteration) + +## Conversion + +- [String To Array + Conversion](20201112102537-javascript_string_to_array_conversion) + +# Operators + +- [In Operator](20201113090337-javascript_in_operator) +- [Instanceof Operator](20201113094246-javascript_instanceof_operator) + +# Objects + +## Keywords + +- [New Keyword](20201113093910-javascript_new_keyword) + +## Functions + +- [Object.is](20201113095300-object_is) +- [Object.assign](20201113095244-object_assign) +- [Object.keys](20201113095226-object_keys) + +# Arrays + +## Prototype methods + +- [Array.prototype.fill()](20201113104217-array_prototype_fill) +- [Array.prototype.copyWithin()](20201113104240-array_prototype_copywithin) + +### Prototype Search Methods + +- [Array.prototype.find()](20201113104352-array_prototype_find) +- [Array.prototype.findIndex()](20201113104332-array_prototype_findindex) + +### Prototype Iteration Methods + +- [Array.prototype.keys()](20201113104454-array_prototype_keys) +- [Array.prototype.entries()](20201113104423-array_prototype_entries) + +## Array functions + +- [Array.of()](20201113105847-array_of) +- [Array.from()](20201113105832-array_from) + +# Data Structures + +- [Maps](20201012093745-javascript_maps) + +# Symbols + +- [Symbols](20201113092454-javascript_symbols) + +# Numbers + +## Notations + +- [Binary Notation](20201116164748-binary_notation) +- [Octal Notation](20201116164828-octal_notation) + +# Footnotes + +[^1]: diff --git a/content/wiki/20201030093832-javascript_if_statement.md b/content/wiki/20201030093832-javascript_if_statement.md new file mode 100644 index 0000000..4227672 --- /dev/null +++ b/content/wiki/20201030093832-javascript_if_statement.md @@ -0,0 +1,20 @@ +--- +date: 2020-10-30 +id: 3791e37d-c3cd-4e61-8802-76eeee25c08b +title: JavaScript If Statement +--- + +# Syntax + +``` javascript +if(true === true) { + console.log("True is true") +} + +if (true === false) { + console.log("True is false") +} +else { + console.log("True is not false") +} +``` diff --git a/content/wiki/20201030094040-javascript_for_statement.md b/content/wiki/20201030094040-javascript_for_statement.md new file mode 100644 index 0000000..ed24571 --- /dev/null +++ b/content/wiki/20201030094040-javascript_for_statement.md @@ -0,0 +1,13 @@ +--- +date: 2020-10-30 +id: f39d2479-e3e5-45dc-8515-93074995a0d6 +title: JavaScript For Statement +--- + +# Syntax + +``` javascript +for(let k = 0; k <= 5; k++) { + console.log("For loop k " + k) +} +``` diff --git a/content/wiki/20201030094138-javascript_switch_statement.md b/content/wiki/20201030094138-javascript_switch_statement.md new file mode 100644 index 0000000..78527dc --- /dev/null +++ b/content/wiki/20201030094138-javascript_switch_statement.md @@ -0,0 +1,51 @@ +--- +date: 2020-10-30 +id: 7af3c0d0-b8aa-4619-81eb-cad43b3698bb +title: JavaScript Switch Statement +--- + +# Syntax + +``` javascript +switch ("rainy") { + case "rainy": + console.log("Remember to bring an umbrella."); + break; + case "sunny": + console.log("Dress lightly."); + case "cloudy": + console.log("Go outside."); + break; + default: + console.log("Unknown weather type!"); + break; +} + +switch ("sunny") { + case "rainy": + console.log("Remember to bring an umbrella."); + break; + case "sunny": + console.log("Dress lightly."); + case "cloudy": + console.log("Go outside."); + break; + default: + console.log("Unknown weather type!"); + break; +} + +switch ("wild card") { + case "rainy": + console.log("Remember to bring an umbrella."); + break; + case "sunny": + console.log("Dress lightly."); + case "cloudy": + console.log("Go outside."); + break; + default: + console.log("Unknown weather type!"); + break; +} +``` diff --git a/content/wiki/20201030094343-javascript_breaking_out_of_a_loop.md b/content/wiki/20201030094343-javascript_breaking_out_of_a_loop.md new file mode 100644 index 0000000..b5ef858 --- /dev/null +++ b/content/wiki/20201030094343-javascript_breaking_out_of_a_loop.md @@ -0,0 +1,16 @@ +--- +date: 2020-10-30 +id: 3b67edf8-727e-42c4-b46d-c096b2fb350b +title: JavaScript Breaking Out of a Loop +--- + +# Syntax + +``` javascript +for (let current = 20; ; current = current + 1) { + if (current % 7 == 0) { + console.log(current); + break; + } +} +``` diff --git a/content/wiki/20201030094749-javascript_comments.md b/content/wiki/20201030094749-javascript_comments.md new file mode 100644 index 0000000..3eeee88 --- /dev/null +++ b/content/wiki/20201030094749-javascript_comments.md @@ -0,0 +1,16 @@ +--- +date: 2020-10-30 +id: 8b7b6ab5-edd5-40d2-85eb-1039b9f3b8be +title: JavaScript Comments +--- + +``` javascript +// This is a one line comment +let i = 0 + +/** + This is a multi line comment + Here is the second line +*/ +let j = 0 +``` diff --git a/content/wiki/20201030095105-es2018.md b/content/wiki/20201030095105-es2018.md new file mode 100644 index 0000000..d156c67 --- /dev/null +++ b/content/wiki/20201030095105-es2018.md @@ -0,0 +1,33 @@ +--- +date: 2020-10-30 +id: 61655397-abe9-4d42-9184-62a9e693fd7b +title: ES2018 +--- + +# Introduction + +What's new in ES2018 + +# Iterations + +- [Asynchronous iteration](20201030092200-javascript_async_iterator) +- [For Await Of](20201030095741-javascript_for_await_of) + +# Rest/Spread Properties + +- [Rest Operator (…) in Object + Destructuring](20201103111357-rest_operator_in_object_destructuring) + +# RegExp + +- [JavaScript RegExp Named Capture + Groups](20201104100431-javascript_regexp_named_capture_groups) +- [JavaScript RegExp Unicode Property + Escapes](20201106090634-javascript_regexp_unicode_property_escapes) +- [JavaScript Lookbehind + Assertions](20201109132944-javascript_lookbehind_assertions) +- [JavaScript RegExp /s flag](20201110094807-javascript_regexp_s_flag) + +# Promises + +- [Finally](20201111095454-javascript_promises_finally) diff --git a/content/wiki/20201030095741-javascript_for_await_of.md b/content/wiki/20201030095741-javascript_for_await_of.md new file mode 100644 index 0000000..ec0452b --- /dev/null +++ b/content/wiki/20201030095741-javascript_for_await_of.md @@ -0,0 +1,48 @@ +--- +date: 2020-10-30 +id: 3dac2b04-4015-4c1f-847c-5e677aec1fc0 +title: JavaScript For Await Of +--- + +# Syntax + +``` javascript +async function f() { + for await (const x of createAsyncIterable(["a", "b"])) { + console.log(x); + } +} +// Output: +// a +// b +``` + +# Rejections + +Like `await` in [async +functions](20201026103714-javascript_async_functions), th eloop throws +an exception if `next()` returns a rejection: + +``` javascript +function createRejectingIterable() { + return { + [Symbol.asyncIterator]() { + return this; + }, + next() { + return Promise.reject(new Error("Problem!")); + }, + }; +} +(async function () { + // (A) + try { + for await (const x of createRejectingIterable()) { + console.log(x); + } + } catch (e) { + console.error(e); + // Error: Problem! + } +})(); // (B) +``` diff --git a/content/wiki/20201030182939-verbs.md b/content/wiki/20201030182939-verbs.md new file mode 100644 index 0000000..695d70a --- /dev/null +++ b/content/wiki/20201030182939-verbs.md @@ -0,0 +1,8 @@ +--- +date: 2020-10-30 +id: 25aa5740-8a7e-4964-bf3f-4391aaf74690 +title: Verbs +--- + +- [geld](20201030183019-geld) +- [percolate](20201109121108-percolate) diff --git a/content/wiki/20201030183019-geld.md b/content/wiki/20201030183019-geld.md new file mode 100644 index 0000000..7a8a2f8 --- /dev/null +++ b/content/wiki/20201030183019-geld.md @@ -0,0 +1,14 @@ +--- +date: 2020-10-30 +id: 511b93dd-0c93-47db-b45f-2c0b21d977f1 +title: geld +--- + +# Noun + +A tax paid to the crown by English landholders under the Anglo-Saxon and +Norman kings + +# Transitive Verbs + +- To castrate (a horse, for example) diff --git a/content/wiki/20201030183237-nouns.md b/content/wiki/20201030183237-nouns.md new file mode 100644 index 0000000..3e9ccc9 --- /dev/null +++ b/content/wiki/20201030183237-nouns.md @@ -0,0 +1,23 @@ +--- +date: 2020-10-30 +id: 9aa93084-5a56-41e7-9753-c582a922ddab +title: Nouns +--- + +- [anathema](20201109122445-anathema) +- [antecedent](20201030195742-antecedent) +- [anteroom](20201109123452-anteroom) +- [antimacassar](20201109122731-antimacassar) +- [chenille](20201109121858-chenille) +- [chiffonier](20201104090229-chiffonier) +- [decanter](20201109123736-decanter) +- [epaulet](20201109121407-epaulet) +- [gaberdine](20201109123003-gaberdine) +- [geld](20201030183019-geld) +- [insouciance](20201109121245-insouciance) +- [mirth](20201109121522-mirth) +- [précis](20201109122314-precis) +- [prig](20201109122557-prig) +- [rancor](20201109123923-rancor) +- [viscosity](20210405123214-viscosity) +- [worsted](20201109123326-worsted) diff --git a/content/wiki/20201030195742-antecedent.md b/content/wiki/20201030195742-antecedent.md new file mode 100644 index 0000000..9416a7c --- /dev/null +++ b/content/wiki/20201030195742-antecedent.md @@ -0,0 +1,15 @@ +--- +date: 2020-10-30 +id: 3bf83aca-1dfb-4a1e-9769-30bd47b2b337 +title: antecedent +--- + +# Noun + +1. a thing that existed before or logically precedes another. +2. a person's ancestors or family and social background. + +# Adjective + +1. preceding in time or order; previous or pre-existing. +2. denoting or counting as an antecedent. diff --git a/content/wiki/20201103111357-rest_operator_in_object_destructuring.md b/content/wiki/20201103111357-rest_operator_in_object_destructuring.md new file mode 100644 index 0000000..b5a96d2 --- /dev/null +++ b/content/wiki/20201103111357-rest_operator_in_object_destructuring.md @@ -0,0 +1,35 @@ +--- +date: 2020-11-03 +id: 78ef5b06-a541-4e33-9c51-af92cd91719c +title: Rest Operator (…) in Object Destructuring +--- + +# Introduction + +Introduced in [ES2018](20201030095105-es2018) to help with +[destructuring](20200922160850-destructuring). + +# Syntax + +## Basic + +``` javascript +const obj = { foo: 1, bar: 2, baz: 3 }; +const { foo, ...rest } = obj; + +console.log(foo); // 1 +console.log(rest); // { bar: 2, baz: 3 } +``` + +## Named parameters + +The rest operator can also be used with [named +parameters](20200922162127-named_parameters): + +``` javascript +function func({ param1, param2, ...rest }) { + // rest operator + console.log("All parameters: ", { param1, param2, ...rest }); // spread operator + return param1 + param2; +} +``` diff --git a/content/wiki/20201103111509-destructuring_arrays.md b/content/wiki/20201103111509-destructuring_arrays.md new file mode 100644 index 0000000..f05c14a --- /dev/null +++ b/content/wiki/20201103111509-destructuring_arrays.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-03 +id: 05066fdd-18fe-4762-b836-af35ba1f625b +title: Destructuring Arrays +--- + +# Introduction + +Destructuring [arrays](20200826201029-arrays) was introduced in +[ES6](20201030093404-es6). +[Iterables](20201103112001-destructuring_iterables) can also be +destructured via the same principle. + +# Syntax + +``` javascript +const [, year, month, day] = + /^(\d\d\d\d)-(\d\d)-(\d\d)$/ + .exec('2999-12-31'); + +console.log(`${year} ${month} ${day}`) // 2999 12 31 +``` diff --git a/content/wiki/20201103111746-destructuring_objects.md b/content/wiki/20201103111746-destructuring_objects.md new file mode 100644 index 0000000..81e4e67 --- /dev/null +++ b/content/wiki/20201103111746-destructuring_objects.md @@ -0,0 +1,21 @@ +--- +date: 2020-11-03 +id: b817ea12-eeeb-4723-a90c-f016cdcdb866 +title: Destructuring Objects +--- + +# Introduction + +Destructuring [objects](20200826201605-objects) introduced in +[ES6](20201030093404-es6). [Rest +Operator](20201103111357-rest_operator_in_object_destructuring) can also +be used here. + +# Syntax + +``` javascript +const saviour = { first: "Jonn", last: "Connor" }; +const { f, l } = saviour; + +console.log(saviour, f, l); // { first: 'John', last: 'Connor' } John Connor +``` diff --git a/content/wiki/20201103112001-destructuring_iterables.md b/content/wiki/20201103112001-destructuring_iterables.md new file mode 100644 index 0000000..e705d44 --- /dev/null +++ b/content/wiki/20201103112001-destructuring_iterables.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-03 +id: 96e9e4f6-8d7d-4a46-85ef-7cb3eb3804df +title: Destructuring Iterables +--- + +# Introduction + +This was introduced in [ES6](20201030093404-es6). Destructuring +[iterables](20201014092625-javascript_iterables) works on the same +principle as [arrays](20201103111509-destructuring_arrays). + +# Syntax + +``` javascript +const [x,...y] = 'abc' +console.log(x, y) // a ['b', 'c'] +``` diff --git a/content/wiki/20201103113124-destructuring_default_values.md b/content/wiki/20201103113124-destructuring_default_values.md new file mode 100644 index 0000000..a66046c --- /dev/null +++ b/content/wiki/20201103113124-destructuring_default_values.md @@ -0,0 +1,37 @@ +--- +date: 2020-11-03 +id: eb8253f8-f376-4b73-9098-35da64a5a6e7 +title: Destructuring Default Values +--- + +# Basic syntax + +``` javascript +const [x=3, y] = [] +console.log(x, y) // 3 undefined +``` + +# Computed on demand + +Default values are computed when they are needed: + +``` javascript +function tralala() { + return "tralala string" +} + +const {computed=tralala()} = {} +console.log(computed) // tralala string +``` + +# Refer to other variables + +Default value an refer to other +[variables](20200613170532-variable_types_in_javascript) in the same +pattern: + +``` javascript +const [x=3, y=x] = []; // x=3; y=3 +const [i=3, j=x] = [7]; // i=7; j=7 +const [k=3, l=x] = [7, 2]; // k=7; l=2 +``` diff --git a/content/wiki/20201104090229-chiffonier.md b/content/wiki/20201104090229-chiffonier.md new file mode 100644 index 0000000..b1a48f9 --- /dev/null +++ b/content/wiki/20201104090229-chiffonier.md @@ -0,0 +1,20 @@ +--- +date: 2020-11-04 +id: 496fd8da-7419-42f3-a1d2-051b96b06e72 +title: chiffonier +--- + +# British[^1] + +a low cupboard either used as a sideboard or with a raised bookshelf on +top. + +# North American[^2] + +a tall chest of drawers. + +# Footnotes + +[^1]: + +[^2]: diff --git a/content/wiki/20201104090504-furniture.md b/content/wiki/20201104090504-furniture.md new file mode 100644 index 0000000..7e68e2c --- /dev/null +++ b/content/wiki/20201104090504-furniture.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-04 +id: d37f69bb-0b66-42ed-be9f-c485ab8d19ca +title: Furniture +--- + +- [antimacassar](20201109122731-antimacassar) +- [chiffonier](20201104090229-chiffonier) diff --git a/content/wiki/20201104095851-javascript_regexp_numbered_capture_groups.md b/content/wiki/20201104095851-javascript_regexp_numbered_capture_groups.md new file mode 100644 index 0000000..376f458 --- /dev/null +++ b/content/wiki/20201104095851-javascript_regexp_numbered_capture_groups.md @@ -0,0 +1,37 @@ +--- +date: 2020-11-04 +id: 66a8f9f2-9d57-4467-bf41-a84eb4b3d10d +title: JavaScript RegExp Numbered Capture Groups +--- + +# Examples + +## Subexpressions + +When the regular expression contains subexpressions grouped with +parentheses, the text that matched those groups will also show up in the +array. The whole match is always the first element. The next element is +the part matched by the first group (the one whose opening parenthesis +comes first in the expression), then the second group, and so on. + +``` javascript +let quotedText = /'([^']*)'/; +console.log(quotedText.exec("she said 'hello'")); +``` + +## No matches + +When a group does not end up being matched at all (for example, when +followed by a question mark), its position in the output array will hold +undefined. Similarly, when a group is matched multiple times, only the +last match ends up in the array. + +``` javascript +console.log(/bad(ly)?/.exec("bad")); +console.log(/(\d)+/.exec("123")); +``` + +# See also + +[Named capture +groups](20201104100431-javascript_regexp_named_capture_groups) diff --git a/content/wiki/20201104100431-javascript_regexp_named_capture_groups.md b/content/wiki/20201104100431-javascript_regexp_named_capture_groups.md new file mode 100644 index 0000000..4a46970 --- /dev/null +++ b/content/wiki/20201104100431-javascript_regexp_named_capture_groups.md @@ -0,0 +1,140 @@ +--- +date: 2020-11-04 +id: cd472cb3-445c-4c81-a133-d6ef13eec545 +title: JavaScript RegExp Named Capture Groups +--- + +# Introduction + +This was introduced in [ES2018](20201030095105-es2018) + +# Proposal + +RegExp Named Capture Groups[^1] + +# Syntax + +``` javascript +const RE_DATE = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/; + +const matchObj = RE_DATE.exec("1999-12-31"); + +console.log(matchObj.groups.year); // 1999 +console.log(matchObj.groups.month); // 12 +console.log(matchObj.groups.day); // 31 +``` + +## Indexed entries + +Named capture groups also created indexed entries, like [numbered +capture +groups](20201104095851-javascript_regexp_numbered_capture_groups) + +``` javascript +const RE_DATE = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/; + +const matchObj = RE_DATE.exec("1999-12-31"); + +console.log(matchObj[1]); // 1999 +console.log(matchObj[2]); // 12 +console.log(matchObj[3]); // 31 +``` + +## Destructuring + +[Destructuring](20201103111746-destructuring_objects) works well with +this: + +``` javascript +const RE_DATE = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/; + +const {groups: {day, year}} = RE_DATE.exec('1999-12-31'); +console.log(year); // 1999 +console.log(day); // 31 +``` + +## Backreferences + +`\k` matches the string that was previously matched by the named +capture group `name`: + +``` javascript +const RE_TWICE = /^(?[a-z]+)!\k$/; +RE_TWICE.test("abc!abc"); // true +RE_TWICE.test("abc!ab"); // false +``` + +Backreference syntax for [numbered capture +groups](20201104095851-javascript_regexp_numbered_capture_groups) works +as well: + +``` javascript +const RE_TWICE = /^(?[a-z]+)!\1$/; +RE_TWICE.test('abc!abc'); // true +RE_TWICE.test('abc!ab'); // false +``` + +Both can be mixed: + +``` javascript +const RE_TWICE = /^(?[a-z]+)!\k!\1$/; +RE_TWICE.test("abc!abc!abc"); // true +RE_TWICE.test("abc!abc!ab"); // false +``` + +## repalce() and named capture groups + +[replace()](20201104102343-javascript_regexp_replace_method) supports +named capture groups in two ways: + +### Mention names in replacement string + +``` javascript +const RE_DATE = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/; +console.log("1999-12-31".replace(RE_DATE, "$/$/$")); +// 12/31/1999 +``` + +### Each replacement function receives an additional parameter that holds an object with data captured via named groups + +``` javascript +const RE_DATE = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/; +console.log( + "1999-12-31".replace( + RE_DATE, + ( + g0, + y, + m, + d, + offset, + input, + { year, month, day } // (A) + ) => month + "/" + day + "/" + year + ) +); +// 12/31/1999 +``` + +[Rest parameters](20200922162500-rest_parameters) can also be used to +access the last argument: + +``` javascript +const RE_DATE = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/; +console.log( + "1999-12-31".replace(RE_DATE, (...args) => { + const { year, month, day } = args[args.length - 1]; + return month + "/" + day + "/" + year; + }) +); +// 12/31/1999 +``` + +# See also + +- [Numbered Capture + Groups](20201104095851-javascript_regexp_numbered_capture_groups) + +# Footnotes + +[^1]: diff --git a/content/wiki/20201104101723-javascript_regexp_test_method.md b/content/wiki/20201104101723-javascript_regexp_test_method.md new file mode 100644 index 0000000..0e5d065 --- /dev/null +++ b/content/wiki/20201104101723-javascript_regexp_test_method.md @@ -0,0 +1,21 @@ +--- +date: 2020-11-04 +id: eff92c39-8459-4f55-a34b-d924eb603056 +title: JavaScript RegExp Test Method +--- + +test[^1] returns true/false: + +``` javascript +let re1 = new RegExp("abc"); +let re2 = /abc/; + +console.log(re1.test("abc")) // true +console.log(re1.test("acd")) // false +console.log(/abc/.test("abcde")) // true +console.log(/abc/.test("abxde")) // false +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201104101924-javascript_regexp_exec_method.md b/content/wiki/20201104101924-javascript_regexp_exec_method.md new file mode 100644 index 0000000..1b8f5c5 --- /dev/null +++ b/content/wiki/20201104101924-javascript_regexp_exec_method.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-04 +id: 879b1425-8e59-4a5b-a2d8-08838e193b88 +title: JavaScript RegExp Exec Method +--- + +exec[^1] returns `null` if no match was found or an object with +information about the match otherwise: + +``` javascript +let match = /\d+/.exec("one two 100"); +console.log(match); +console.log(match.index); +``` + +# See also + +- [match](20201104102212-javascript_regexp_match_method) + +# Footnotes + +[^1]: diff --git a/content/wiki/20201104102212-javascript_regexp_match_method.md b/content/wiki/20201104102212-javascript_regexp_match_method.md new file mode 100644 index 0000000..036e12b --- /dev/null +++ b/content/wiki/20201104102212-javascript_regexp_match_method.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-04 +id: dc5b49fe-a371-459a-b82b-174301aee41d +title: JavaScript RegExp Match Method +--- + +\`match\` is similar to +[exec](20201104101924-javascript_regexp_exec_method), but in flip mode: + +``` javascript +console.log("one two 100".match(/\d+/)); +``` diff --git a/content/wiki/20201104102343-javascript_regexp_replace_method.md b/content/wiki/20201104102343-javascript_regexp_replace_method.md new file mode 100644 index 0000000..eb0f55f --- /dev/null +++ b/content/wiki/20201104102343-javascript_regexp_replace_method.md @@ -0,0 +1,47 @@ +--- +date: 2020-11-04 +id: 11d0fefd-c11e-400b-80fd-ba40e94b2a47 +title: JavaScript RegExp Replace Method +--- + +replace[^1] is a nice way to use regexps to replace text: + +``` javascript +console.log("papa".replace("p", "m")); +console.log("Borobudur".replace(/[ou]/, "a")); +console.log("Borobudur".replace(/[ou]/g, "a")); +``` + +You can also use awk like syntax to switch things around: + +``` javascript +console.log( + "Liskov, Barbara\nMcCarthy, John\nWadler, Philip" + .replace(/(\w+), (\w+)/g, "$2 $1")); +``` + +You can even pass a function to replace: + +``` javascript +let s = "the cia and fbi"; +console.log(s.replace(/\b(fbi|cia)\b/g, + str => str.toUpperCase())); +``` + +``` javascript +let stock = "1 lemon, 2 cabbages, and 101 eggs"; +function minusOne(match, amount, unit) { + amount = Number(amount) - 1; + if (amount == 1) { // only one left, remove the 's' + unit = unit.slice(0, unit.length - 1); + } else if (amount == 0) { + amount = "no"; + } + return amount + " " + unit; +} +console.log(stock.replace(/(\d+) (\w+)/g, minusOne)); +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201104102506-javascript_regexp_search_method.md b/content/wiki/20201104102506-javascript_regexp_search_method.md new file mode 100644 index 0000000..73992e8 --- /dev/null +++ b/content/wiki/20201104102506-javascript_regexp_search_method.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-04 +id: cc0d1937-ec92-4a2f-802d-f5fbde4e61b2 +title: JavaScript RegExp Search Method +--- + +``` javascript +console.log(" word".search(/\S/)); // 2 +console.log(" ".search(/\S/)); // -1 +``` diff --git a/content/wiki/20201106090634-javascript_regexp_unicode_property_escapes.md b/content/wiki/20201106090634-javascript_regexp_unicode_property_escapes.md new file mode 100644 index 0000000..6268dd6 --- /dev/null +++ b/content/wiki/20201106090634-javascript_regexp_unicode_property_escapes.md @@ -0,0 +1,85 @@ +--- +date: 2020-11-06 +id: 5441479c-12e5-48c1-ab17-46a9c3df8bc3 +title: JavaScript RegExp Unicode Property Escapes +--- + +# Description + +Characters can be matched by mentioning their Unicode character +properties inside of `\p{}`: + +# Proposal + +RegExp Unicode Property Escapes[^1] + +# Syntax + +``` javascript +console.log(/^\p{White_Space}+$/u.test("\t \n\r")); // true +console.log(/^\p{Script=Greek}+$/u.test("μετά")); // true +``` + +# Properties + +## Examples + +### Name + +A unique name, composed of uppercase letters, digits, hyphens and +spaces. + +- A: Name = LATIN CAPITAL LETTER A +- 🙂: Name = SLIGHTLY SMILING FACE + +### General~Category~ + +categorizes characters + +- x: General~Category~ = Lowercase~Letter~ +- \$: General~Category~ = Currency~Symbol~ + +### White~Scpace~ + +Used for marking invisible spacing characters, such as spaces, tabs and +newlines. + +- :͡ White~Space~ = True +- π: White~Space~ = False + +### Age + +Version of the Unicode Standard in which a character was introduced. For +example: The Euro sign € was added in version 2.1 of the Unicode +standard. + +- €: Age = 2.1 + +### Block + +A contiguous range of code points. Blocks don’t overlap and their names +are unique. + +- S: Block = Basic~Latin~ (range U+0000..U+007F) +- 🙂: Block = Emoticons (range U+1F600..U+1F64F) + +### Script + +A collection of characters used by one or more writing systems. + +- Some scripts support several writing systems. For example, the Latin + script supports the writing systems English, French, German, Latin, + etc. +- Some languages can be written in multiple alternate writing systems + that are supported by multiple scripts. For example, Turkish used + the Arabic script before it transitioned to the Latin script in the + early 20th century. + +1. Examples + + - α: Script = Greek + - Д: Script = Cyrillic + +# Footnotes + +[^1]: diff --git a/content/wiki/20201109120843-chess_terms.md b/content/wiki/20201109120843-chess_terms.md new file mode 100644 index 0000000..03a3f13 --- /dev/null +++ b/content/wiki/20201109120843-chess_terms.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 1a8dc89a-20b8-4f11-9945-1ffec02841bb +title: Chess Terms +--- + +- [fianchetto](20201109120912-fianchetto) diff --git a/content/wiki/20201109120912-fianchetto.md b/content/wiki/20201109120912-fianchetto.md new file mode 100644 index 0000000..3d92b60 --- /dev/null +++ b/content/wiki/20201109120912-fianchetto.md @@ -0,0 +1,13 @@ +--- +date: 2020-11-09 +id: e25e14da-75fa-4810-9245-01a11b878a4b +title: fianchetto +--- + +Fianchetto[^1] is a pattern of development wherein a bishop is developed +to the second rank of the adjacent b- or g-file, the knight pawn having +been moved one or two squares forward. + +# Footnotes + +[^1]: diff --git a/content/wiki/20201109121108-percolate.md b/content/wiki/20201109121108-percolate.md new file mode 100644 index 0000000..713645b --- /dev/null +++ b/content/wiki/20201109121108-percolate.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 36bda200-ac74-4892-818c-935278e530f2 +title: percolate +--- + +To cause (liquid) to diff --git a/content/wiki/20201109121245-insouciance.md b/content/wiki/20201109121245-insouciance.md new file mode 100644 index 0000000..84928d1 --- /dev/null +++ b/content/wiki/20201109121245-insouciance.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 92388ae4-a34c-4245-b7c3-cfa9a161153c +title: insouciance +--- + +Blithe lack of concern; nonchalance diff --git a/content/wiki/20201109121407-epaulet.md b/content/wiki/20201109121407-epaulet.md new file mode 100644 index 0000000..f5d5f23 --- /dev/null +++ b/content/wiki/20201109121407-epaulet.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-09 +id: 050827d4-a429-4121-867c-74cd9c11c768 +title: epaulet +--- + +A shoulder ornament, especially a fringed strap worn on military +uniforms diff --git a/content/wiki/20201109121522-mirth.md b/content/wiki/20201109121522-mirth.md new file mode 100644 index 0000000..495e382 --- /dev/null +++ b/content/wiki/20201109121522-mirth.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 40ae2826-3e7a-4243-a263-25df821a0c9e +title: mirth +--- + +gladness or gaiety as shown by or accompanied with laughter diff --git a/content/wiki/20201109121645-imperturbable.md b/content/wiki/20201109121645-imperturbable.md new file mode 100644 index 0000000..b97aec3 --- /dev/null +++ b/content/wiki/20201109121645-imperturbable.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 0b581a57-6837-4786-9d9c-c70d0c1d425c +title: imperturbable +--- + +Unshakably calm and collected diff --git a/content/wiki/20201109121740-wily.md b/content/wiki/20201109121740-wily.md new file mode 100644 index 0000000..a16a3cc --- /dev/null +++ b/content/wiki/20201109121740-wily.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: a409e6e3-f7d7-4075-b8ec-e1c9cf77551e +title: wily +--- + +Crafty diff --git a/content/wiki/20201109121858-chenille.md b/content/wiki/20201109121858-chenille.md new file mode 100644 index 0000000..44e1b3c --- /dev/null +++ b/content/wiki/20201109121858-chenille.md @@ -0,0 +1,13 @@ +--- +date: 2020-11-09 +id: fdd61541-806e-4f10-94a5-163cc9e91dfa +title: chenille +--- + +Chenille[^1] may refer to either a type of yarn or fabric made from it. +Chenille is the French word for caterpillar whose fur the yarn is +supposed to resemble. + +# Footnotes + +[^1]: diff --git a/content/wiki/20201109122104-tongue_twisters.md b/content/wiki/20201109122104-tongue_twisters.md new file mode 100644 index 0000000..238bcf6 --- /dev/null +++ b/content/wiki/20201109122104-tongue_twisters.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 16267039-12a7-45f5-8b5c-27e0f5f7c0e1 +title: Tongue Twisters +--- + +- Peter Piper picked a peck of pickled peppers diff --git a/content/wiki/20201109122314-precis.md b/content/wiki/20201109122314-precis.md new file mode 100644 index 0000000..549fe20 --- /dev/null +++ b/content/wiki/20201109122314-precis.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 42ca54aa-d214-47e4-aed9-d6fda75930cc +title: précis +--- + +A concise summary of essential points, statements, or facts diff --git a/content/wiki/20201109122445-anathema.md b/content/wiki/20201109122445-anathema.md new file mode 100644 index 0000000..782c355 --- /dev/null +++ b/content/wiki/20201109122445-anathema.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: a371dd28-5353-46ca-91fc-5c9bf3b86a2d +title: anathema +--- + +- A formal ecclestiastical ban, curse, or excommunicatio diff --git a/content/wiki/20201109122557-prig.md b/content/wiki/20201109122557-prig.md new file mode 100644 index 0000000..c218eaf --- /dev/null +++ b/content/wiki/20201109122557-prig.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-09 +id: bfb8476f-98b3-4021-b01f-b108f12a36ad +title: prig +--- + +A person who demonstrates an exaggerated conformity or propriety, +especially in an irritatingly arrogant or smug manner. diff --git a/content/wiki/20201109122731-antimacassar.md b/content/wiki/20201109122731-antimacassar.md new file mode 100644 index 0000000..49155b7 --- /dev/null +++ b/content/wiki/20201109122731-antimacassar.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: fbfd461d-c841-4279-a6ca-62cec10ea23e +title: antimacassar +--- + +A protective covering for the back of a chair or sofa diff --git a/content/wiki/20201109122833-perfunctory.md b/content/wiki/20201109122833-perfunctory.md new file mode 100644 index 0000000..f056b45 --- /dev/null +++ b/content/wiki/20201109122833-perfunctory.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 8fbe411f-3009-43fc-a974-b6a51810aa23 +title: perfunctory +--- + +Done routinely and with little interest or care. diff --git a/content/wiki/20201109123003-gaberdine.md b/content/wiki/20201109123003-gaberdine.md new file mode 100644 index 0000000..7e43630 --- /dev/null +++ b/content/wiki/20201109123003-gaberdine.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-09 +id: 7521bc64-b435-4168-a003-4783cbd5a835 +title: gaberdine +--- + +Gaberdine[^1] is a long, loose gown or cloak with wide sleeves, worm by +men in the later Middle Ages and into the 16t + +# Footnotes + +[^1]: diff --git a/content/wiki/20201109123123-clothing.md b/content/wiki/20201109123123-clothing.md new file mode 100644 index 0000000..90fb573 --- /dev/null +++ b/content/wiki/20201109123123-clothing.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-09 +id: 88e3b0d4-581e-4bc6-8a29-621fd8291040 +title: Clothing +--- + +- [chenille](20201109121858-chenille) +- [epaulet](20201109121407-epaulet) +- [gaberdine](20201109123003-gaberdine) +- [worsted](20201109123326-worsted) diff --git a/content/wiki/20201109123326-worsted.md b/content/wiki/20201109123326-worsted.md new file mode 100644 index 0000000..73bd6f6 --- /dev/null +++ b/content/wiki/20201109123326-worsted.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-09 +id: decaf084-f16e-498b-8380-0acadf7f6662 +title: worsted +--- + +- Firm-textured, compactly twisted woolen yarn made from long-staple + fibers +- Fabric made from such yarn diff --git a/content/wiki/20201109123452-anteroom.md b/content/wiki/20201109123452-anteroom.md new file mode 100644 index 0000000..5527d89 --- /dev/null +++ b/content/wiki/20201109123452-anteroom.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-09 +id: db151c94-a2a0-47b9-9a03-ea629f7cddc6 +title: anteroom +--- + +1. An outer room that opens into another room, often used as a waiting + room. +2. A smaller room before a chief apartment, to which access is had + through it; especially, a waiting-room used for the temporary + reception of visitors, etc.; an antechamber. +3. A room before, or forming an entrance to, another; a waiting room. diff --git a/content/wiki/20201109123541-architecture.md b/content/wiki/20201109123541-architecture.md new file mode 100644 index 0000000..f3851ad --- /dev/null +++ b/content/wiki/20201109123541-architecture.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 9ac5d3fd-0bc6-4355-ac69-801cd0377dea +title: Architecture +--- + +- [anteroom](20201109123452-anteroom) diff --git a/content/wiki/20201109123624-sanguine.md b/content/wiki/20201109123624-sanguine.md new file mode 100644 index 0000000..ff4b798 --- /dev/null +++ b/content/wiki/20201109123624-sanguine.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: ce921d25-c0f3-491c-970d-9c03f0b30322 +title: sanguine +--- + +Marked by eager hopefulness: confidently optimistic diff --git a/content/wiki/20201109123736-decanter.md b/content/wiki/20201109123736-decanter.md new file mode 100644 index 0000000..f13b9e7 --- /dev/null +++ b/content/wiki/20201109123736-decanter.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-09 +id: b5bd34f7-8004-4af4-91fa-0b794b3a0e09 +title: decanter +--- + +Decanter[^1] is a vessel that is used to hold the decantation of a +liquid (such as wine) + +# Footnotes + +[^1]: diff --git a/content/wiki/20201109123853-glassware.md b/content/wiki/20201109123853-glassware.md new file mode 100644 index 0000000..ecd94ff --- /dev/null +++ b/content/wiki/20201109123853-glassware.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 9577779f-1bb0-49a1-ab58-3b0063ecc7d0 +title: Glassware +--- + +- [decanter](20201109123736-decanter) diff --git a/content/wiki/20201109123923-rancor.md b/content/wiki/20201109123923-rancor.md new file mode 100644 index 0000000..bb8d19a --- /dev/null +++ b/content/wiki/20201109123923-rancor.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-09 +id: 719ec7b9-bde6-4d04-9e83-8d1f130ea507 +title: rancor +--- + +- Bitter, long lasting resentment; deep-seated ill will. +- Sourness; bitterness. diff --git a/content/wiki/20201109124059-eidetic.md b/content/wiki/20201109124059-eidetic.md new file mode 100644 index 0000000..9af2a60 --- /dev/null +++ b/content/wiki/20201109124059-eidetic.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-09 +id: eeaf10ea-aec0-4f0b-9d76-f2439c1e010e +title: eidetic +--- + +- Of, relating to, or marked by extraordinarily detailed and vivid + recall of visual images. diff --git a/content/wiki/20201109124204-inchmeal.md b/content/wiki/20201109124204-inchmeal.md new file mode 100644 index 0000000..edc0a8c --- /dev/null +++ b/content/wiki/20201109124204-inchmeal.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: eccd4be7-594c-485e-9fcd-a5e2e1ccdebf +title: inchmeal +--- + +Little by little; gradually diff --git a/content/wiki/20201109132457-javascript_lookahead_assertions.md b/content/wiki/20201109132457-javascript_lookahead_assertions.md new file mode 100644 index 0000000..53a913f --- /dev/null +++ b/content/wiki/20201109132457-javascript_lookahead_assertions.md @@ -0,0 +1,29 @@ +--- +date: 2020-11-09 +id: 3ab00edf-6c63-4db2-b32e-d18f8d683329 +title: JavaScript Lookahead Assertions +--- + +# Examples + +## Positive lookahead assertion + +Text after the current location must match the assertion + +``` javascript +const RE_AS_BS = /aa(?=bb)/; +const match1 = RE_AS_BS.exec("aabb"); +console.log(match1[0]); // 'aa' +``` + +## Negative lookahead assertion + +Text after the current location must not match the assertion + +``` javascript +const RE_AS_NO_BS = /aa(?!bb)/; + +console.log(RE_AS_NO_BS.test("aabb")); // false +console.log(RE_AS_NO_BS.test("aab")); // true +console.log(RE_AS_NO_BS.test("aac")); // true +``` diff --git a/content/wiki/20201109132944-javascript_lookbehind_assertions.md b/content/wiki/20201109132944-javascript_lookbehind_assertions.md new file mode 100644 index 0000000..b874e04 --- /dev/null +++ b/content/wiki/20201109132944-javascript_lookbehind_assertions.md @@ -0,0 +1,25 @@ +--- +date: 2020-11-09 +id: d1549dd2-a5fc-4583-a186-5de02ca40d33 +title: JavaScript Lookbehind Assertions +--- + +# Examples + +## Positive lookbehind assertion + +Text preceding the current location must match the assertion + +``` javascript +const RE_DOLLAR_PREFIX = /(?<=\$)foo/g; +console.log("$foo %foo foo".replace(RE_DOLLAR_PREFIX, "bar")); // '$bar %foo foo' +``` + +## Negative lookbehind assertion + +Text preceding the current location must not match the assertion + +``` javascript +const RE_NO_DOLLAR_PREFIX = /(? diff --git a/content/wiki/20201109133834-php_8_0.md b/content/wiki/20201109133834-php_8_0.md new file mode 100644 index 0000000..ae6b0a6 --- /dev/null +++ b/content/wiki/20201109133834-php_8_0.md @@ -0,0 +1,72 @@ +--- +date: 2020-11-09 +id: 7ba8d853-d642-45fe-9de8-2d50e6c70b6d +title: PHP 8.0 +--- + +# Changes + +## Types + +- [Union Type](20201109133923-php_union_type) +- [Mixed Type](20201113122959-php_mixed_type) + +## Operators + +- [Nullsafe Operator](20201110100120-php_nullsafe_operator) + +## Attributes + +- [Attributes](20201110100420-php_attributes) + +## Classes + +### Constructors + +- [Constructor Property + Promotion](20201110101308-php_constructor_property_promotion) + +## Return types + +- [Static Return Type](20201110102332-php_static_return_type) + +## Literals + +- [Class Name Literal](20201110102900-php_class_name_literal) + +## Interfaces + +- [Stringable Interface](20201110103409-php_stringable_interface) + +## Maps + +- [Weap Maps](20201110103654-php_weak_maps) + +## Errors + +- [Throw Expression](20201111100807-php_throw_expression) +- [Non-capturing Catches](20201111101148-php_non_capturing_catches) + +## Parameters + +- [Named Arguments](20201112111910-named_arguments) +- [Trailing Comma in Parameter + Lists](20201112113236-trailing_comma_in_parameter_lists) + +## Functions + +- [str~contains~()](20201113115231-str_contains) +- [str~startswith~()](20201113115424-str_starts_with) +- [str~endswith~()](20201113115452-str_ends_with) +- [get~debugtype~()](20201113115939-get_debug_type) +- [get~resourceid~()](20201113120246-get_resource_id) + +## Objects + +### DateTime + +- [createFromInterface()](20201113123327-createfrominterface) + +## Expressions + +- [Match expression](20201113121813-match_expression) diff --git a/content/wiki/20201109133923-php_union_type.md b/content/wiki/20201109133923-php_union_type.md new file mode 100644 index 0000000..d00c831 --- /dev/null +++ b/content/wiki/20201109133923-php_union_type.md @@ -0,0 +1,40 @@ +--- +date: 2020-11-09 +id: cb0583f2-374c-4788-b826-dbb7e5903711 +title: PHP Union Type +--- + +# Description + +Allows multiple possible types\[fn:rc\] to be given to a +parameter/member. + +# Syntax + +``` php +class Example { + private int|float $foo; + + public function __construct(int|float $foo) { + $this->foo = $foo; + } + + public function doSomethingWithMultipleTypes(float|int $bar): int|float { + return ($bar + $this->foo) * 2; + } +} +``` + +# Inheritance + +``` php +class A{ + public function foo(string|int $foo): string|int {} +} + +class B extends A{ + public function foo(string|int|float $foo): string {} +} +``` + +# Footnotes diff --git a/content/wiki/20201109140046-validator_information_in_the_symfony_profiler.md b/content/wiki/20201109140046-validator_information_in_the_symfony_profiler.md new file mode 100644 index 0000000..19f22e8 --- /dev/null +++ b/content/wiki/20201109140046-validator_information_in_the_symfony_profiler.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-09 +id: 91c73796-f9c1-4876-a0c7-07911a7f51e1 +title: Validator information in the Symfony profiler +--- + +Added in [Symfony 4.0](20201109140137-symfony_4_0). Symfony 4.0/3.4 adds +validator information to the Symfony profile diff --git a/content/wiki/20201109140137-symfony_4_0.md b/content/wiki/20201109140137-symfony_4_0.md new file mode 100644 index 0000000..701e432 --- /dev/null +++ b/content/wiki/20201109140137-symfony_4_0.md @@ -0,0 +1,66 @@ +--- +date: 2020-11-09 +id: eaf00cf5-efb7-4f53-b721-4f0592671400 +title: Symfony 4.0 +--- + +# What's new + +## Profiler + +- [Validator information in the Symfony + profiler](20201109140046-validator_information_in_the_symfony_profiler) +- [User impersonation in debug + toolbar](20201109143336-symfony_user_impersonation_in_debug_toolbar) + +## Validation + +### Constraints + +- [ExpressionLanguage + Constraint](20201109150640-expressionlanguage_constraint) +- [Groups support for Valid + constraint](20201109145724-groups_support_for_valid_constraint) + +## Annotations + +- [Prefix all controller route + names](20201109142351-prefix_all_controller_route_names) + +## Subscribers + +- [Subscribing to events in the micro + kernel](20201109150109-subscribing_to_events_in_the_micro_kernel) + +## Components + +### Stopwatch + +- [reset() method](20201109141042-reset_method) +- [Microseconds support](20201109141116-microseconds_support) + +### Command + +- [Lazy Commands](20201109141540-lazy_commands) + +### Translation + +- [XLIFF 2.0](20201109142907-xliff_2_0) + +### Guard + +- [getCredentials() responsibilities + split](20201109152527-getcredentials_responsibilities_split) + +## Sessions + +- [Lazy Sessions](20201109151019-lazy_sessions) + +## Commands + +- [debug:autowiring](20201109151937-debug_autowiring) +- [debug:form](20201109152714-debug_form) + +## Autowiring + +- [Local Service Binding](20201109153159-local_service_binding) diff --git a/content/wiki/20201109140300-symfony.md b/content/wiki/20201109140300-symfony.md new file mode 100644 index 0000000..ac5cca3 --- /dev/null +++ b/content/wiki/20201109140300-symfony.md @@ -0,0 +1,44 @@ +--- +date: 2020-11-09 +id: 1da928dc-a8f2-4039-ae2e-27a2a51eb2ab +title: Symfony +--- + +# Framework + +- [Annotations](20201109142218-symfony_annotations) +- [Attributes](20201117111410-symfony_attributes) +- [Autowiring](20201111111255-symfony_autowiring) +- [Commands](20201109152907-symfony_commands) +- [Components](20201110152627-symfony_components) +- [Configuration](20201112124715-symfony_configuration) +- [Controller](20201117102242-syfony_controller) +- [Doctrine](20201117101232-symfony_doctrine_integration) +- [Encryption](20201113174255-encryption) +- [Events](20201113175016-events) +- [Firewalls](20201113183209-symfony_firewalls) +- [Forms](20201109140450-symfony_forms) +- [JSON](20201112125813-symfony_json) +- [Linters](20201116141414-linters) +- [Listeners](20201113175145-listeners) +- [Passwords](20201112133603-symfony_passwords) +- [Profiler](20201109143227-symfony_profiler) +- [Resolver](20201116142916-symfony_resolver) +- [Routing](20201109142307-symfony_routing) +- [Security](20201116121447-symfony_security) +- [Services](20201112124304-symfony_services) +- [Sessions](20201109150950-sessions) +- [Subscribers](20201113175249-subscribers) +- [User](20201117103021-symfony_user) +- [UTF-8 Support](20201112132858-symfony_utf_8_support) +- [Validation](20201109140430-symfony_validation) + +# Changelog + +- [4.0](20201109140137-symfony_4_0) +- [4.1](20201110152518-symfony_4_1) +- [4.2](20201111101706-symfony_4_2) +- [4.3](20201112120118-symfony_4_3) +- [5.0](20201113172025-symfony_5_0) +- [5.1](20201116105919-symfony_5_1) +- [5.2](20201117095953-symfony_5_2) diff --git a/content/wiki/20201109140430-symfony_validation.md b/content/wiki/20201109140430-symfony_validation.md new file mode 100644 index 0000000..238ae95 --- /dev/null +++ b/content/wiki/20201109140430-symfony_validation.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-09 +id: 8621e3e5-f8d3-42fe-9b22-1a9b5701caba +title: Symfony Validation +--- + +# Forms + +- [Constraints](20201112121938-symfony_constraints) + +# Profiler + +- [Validator information in the Symfony + profiler](20201109140046-validator_information_in_the_symfony_profiler) + +# Doctrine + +- [Automatic Validation Based on Doctrine + Mapping](20201112132007-automatic_validation_based_on_doctrine_mapping) diff --git a/content/wiki/20201109140450-symfony_forms.md b/content/wiki/20201109140450-symfony_forms.md new file mode 100644 index 0000000..d880eb2 --- /dev/null +++ b/content/wiki/20201109140450-symfony_forms.md @@ -0,0 +1,27 @@ +--- +date: 2020-11-09 +id: 167901c3-0082-4b00-bc46-f4be6db0b2d5 +title: Symfony Forms +--- + +# Profiler + +- [Validator information in the Symfony + profiler](20201109140046-validator_information_in_the_symfony_profiler) + +# Commands + +- [debug:form](20201109152714-debug_form) + +# Misc + +- [Clear Form Errors](20201111105422-symfony_clear_form_errors) + +# Types + +- [Week Form Type](20201113182753-week_form_type) + +# Formm data mapper + +- [Callback Functions To Get/Set Form + Fields](20201117103506-callback_functions_to_get_set_form_fields) diff --git a/content/wiki/20201109140848-symfony_stopwatch_component.md b/content/wiki/20201109140848-symfony_stopwatch_component.md new file mode 100644 index 0000000..f22599a --- /dev/null +++ b/content/wiki/20201109140848-symfony_stopwatch_component.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-09 +id: de2f04c0-dd25-4bac-84d2-ae54b6c5ace5 +title: Symfony Stopwatch Component +--- + +# Methods + +- [reset() method](20201109141042-reset_method) +- [Microseconds support](20201109141116-microseconds_support) diff --git a/content/wiki/20201109141042-reset_method.md b/content/wiki/20201109141042-reset_method.md new file mode 100644 index 0000000..973d679 --- /dev/null +++ b/content/wiki/20201109141042-reset_method.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 721aa687-7630-4d01-8ac4-8e77f4aa14a8 +title: reset() method +--- + +Causes the Stopwatch object to be reset to its original state. diff --git a/content/wiki/20201109141116-microseconds_support.md b/content/wiki/20201109141116-microseconds_support.md new file mode 100644 index 0000000..0f71134 --- /dev/null +++ b/content/wiki/20201109141116-microseconds_support.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-09 +id: a76fdbfd-4585-4f98-8f61-f1631421f5c7 +title: Microseconds support +--- + +Since [Symfony 4.0](20201109140137-symfony_4_0) the [Symfony Stopwatch +Component](20201109140848-symfony_stopwatch_component) supports +microseconds. diff --git a/content/wiki/20201109141325-symfony_console_component.md b/content/wiki/20201109141325-symfony_console_component.md new file mode 100644 index 0000000..41a8129 --- /dev/null +++ b/content/wiki/20201109141325-symfony_console_component.md @@ -0,0 +1,52 @@ +--- +date: 2020-11-09 +id: 6c80f9ff-166d-46a0-8498-854ddc21b74a +title: Symfony Console Component +--- + +- [Single Command + Applications](20201116125148-single_command_applications) + +# Colours + +- [True Console Colours](20201117100855-true_console_colours) + +# Commands + +- [Lazy Commands](20201109141540-lazy_commands) + +# Cursor Control + +- [Console Cursor Control](20201116134142-console_cursor_control) + +# Tables + +- [Table Titles](20201111104124-syfmony_console_table_titles) +- [Horizontal Tables](20201113180928-horizontal_tables) + +# Links + +- [Console Hyperlinks](20201112120358-symfony_console_hyperlinks) + +# Lists + +- [Definition Lists](20201113181356-definition_lists) + +# Progress bars + +- [Iterable Progress + Bars](20201112130234-symfony_console_iterable_progress_bars) + +# Signals + +- [Console Signals](20201117114930-console_signals) + +# Style + +- [Symfony Style For + Commands](20201113181152-symfony_style_for_commands) + +# Exit Codes + +- [Command::SUCCESS](20201116141657-command_success) +- [Command::ERROR](20201116141817-command_error) diff --git a/content/wiki/20201109141540-lazy_commands.md b/content/wiki/20201109141540-lazy_commands.md new file mode 100644 index 0000000..79ca0f5 --- /dev/null +++ b/content/wiki/20201109141540-lazy_commands.md @@ -0,0 +1,28 @@ +--- +date: 2020-11-09 +id: 94e8a635-126e-4c26-8176-2020a5e79b26 +title: Lazy Commands +--- + +# Description + +From [Symfony 4.0](20201109140137-symfony_4_0) commands are lazily +loaded. One broken command won't break all the other commands you have. +In order to lazy-load a command do the following: + +- Define command as a service +- Add a `command` property to the `console.command` tag + +# Syntax + +``` yaml +app.command.complex_command: + # ... + tags: + # the value of the 'command' attribute is the name of the command + # (which is what the user needs to type in to execute it) + - { name: console.command, command: app:my-command } + + # optionally you can define an alias for the command too + - { name: console.command, command: app:my-command, alias: 'my-shortcut' } +``` diff --git a/content/wiki/20201109142218-symfony_annotations.md b/content/wiki/20201109142218-symfony_annotations.md new file mode 100644 index 0000000..1e32c7e --- /dev/null +++ b/content/wiki/20201109142218-symfony_annotations.md @@ -0,0 +1,6 @@ +--- +date: 2020-11-09 +id: 74c25bac-fff6-4881-a499-e9ba2e92e72f +title: Symfony Annotations +--- + diff --git a/content/wiki/20201109142307-symfony_routing.md b/content/wiki/20201109142307-symfony_routing.md new file mode 100644 index 0000000..63f523c --- /dev/null +++ b/content/wiki/20201109142307-symfony_routing.md @@ -0,0 +1,16 @@ +--- +date: 2020-11-09 +id: 08460bc3-51d0-4bea-ac17-481bf65508cf +title: Symfony Routing +--- + +- [Symfony Routing + Annotations](20201117105617-symfony_routing_annotations) +- [Attributes](20201117105314-symfony_routing_attributes) + +# Configuration + +## IL8N + +- [Different Hosts Per + Locale](20201116133627-different_hosts_per_locale) diff --git a/content/wiki/20201109142351-prefix_all_controller_route_names.md b/content/wiki/20201109142351-prefix_all_controller_route_names.md new file mode 100644 index 0000000..d3a14f8 --- /dev/null +++ b/content/wiki/20201109142351-prefix_all_controller_route_names.md @@ -0,0 +1,64 @@ +--- +date: 2020-11-09 +id: 0fae8bc3-e520-4515-b3ca-7d8b1003d132 +title: Prefix all controller route names +--- + +# Introduction + +From [Symfony 4.0](20201109140137-symfony_4_0) the class of a controller +can define the `@Route` annotation to set a common prefix for the URLs +used by the action methods: + +# Syntax + +``` php +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; + +/** + * @Route("/blog") + */ +class BlogController extends Controller +{ + /** + * @Route("/", defaults={"page": "1"}, name="blog_index") + * @Route("/page/{page}", name="blog_index_paginated") + */ + public function indexAction($page, $_format) { ... } + + /** + * @Route("/posts/{slug}", name="blog_post") + */ + public function showAction(Post $post) { ... } +} +``` + +Add a `name` property to the `@Route` annotation of the controller class +and that will be considered the prefix of all route names. The following +is equivalent to the previous example: + +``` php +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; + +/** + * @Route("/blog", name="blog_") + */ +class BlogController extends Controller +{ + /** + * @Route("/", defaults={"page": "1"}, name="index") + * @Route("/page/{page}", name="index_paginated") + */ + public function indexAction($page, $_format) { ... } + + /** + * @Route("/posts/{slug}", name="post") + */ + public function showAction(Post $post) { ... } +} +``` + +# name~prefix~ option + +In [Symfony 4.1](20201110152518-symfony_4_1) a new +[name~prefix~](20201110153351-name_prefix) option was added. diff --git a/content/wiki/20201109142805-symfony_translation_component.md b/content/wiki/20201109142805-symfony_translation_component.md new file mode 100644 index 0000000..28d459f --- /dev/null +++ b/content/wiki/20201109142805-symfony_translation_component.md @@ -0,0 +1,6 @@ +--- +date: 2020-11-09 +id: a36e7f58-041b-46f7-9fd8-15bfa73460a1 +title: Symfony Translation Component +--- + diff --git a/content/wiki/20201109142907-xliff_2_0.md b/content/wiki/20201109142907-xliff_2_0.md new file mode 100644 index 0000000..cdd0c2b --- /dev/null +++ b/content/wiki/20201109142907-xliff_2_0.md @@ -0,0 +1,50 @@ +--- +date: 2020-11-09 +id: 36596d9f-7a8e-4018-a28c-e6ed2f727c47 +title: XLIFF 2.0 +--- + +# Introduction + +From [Symfony 4.0](20201109140137-symfony_4_0) XLIFF support has been +added. + +# Syntax + +``` xml + + + + + + new + true + user login + + + original-content + translated-content + + + + +``` + +``` php +$catalogue = new MessageCatalogue('en_US'); +$catalogue->add([ + 'original-content' => 'translated-content', +]); +$catalogue->setMetadata('original-content', ['notes' => [ + ['category' => 'state', 'content' => 'new'], + ['category' => 'approved', 'content' => 'true'], + ['category' => 'section', 'content' => 'user login', 'priority' => '1'], +]]); + +$dumper = new XliffFileDumper(); +$dumper->formatCatalogue($catalogue, 'messages', [ + 'default_locale' => 'fr_FR', + 'xliff_version' => '2.0' +]); +``` diff --git a/content/wiki/20201109143227-symfony_profiler.md b/content/wiki/20201109143227-symfony_profiler.md new file mode 100644 index 0000000..1a6fa5c --- /dev/null +++ b/content/wiki/20201109143227-symfony_profiler.md @@ -0,0 +1,15 @@ +--- +date: 2020-11-09 +id: 09a4ff97-67f5-4b5d-9972-289f71a3ef08 +title: Symfony Profiler +--- + +# Validator + +- [Validator information in the Symfony + profiler](20201109140046-validator_information_in_the_symfony_profiler) + +# User impersonation + +- [Symfony user impersonation in debug + toolbar](20201109143336-symfony_user_impersonation_in_debug_toolbar) diff --git a/content/wiki/20201109143336-symfony_user_impersonation_in_debug_toolbar.md b/content/wiki/20201109143336-symfony_user_impersonation_in_debug_toolbar.md new file mode 100644 index 0000000..29a719f --- /dev/null +++ b/content/wiki/20201109143336-symfony_user_impersonation_in_debug_toolbar.md @@ -0,0 +1,6 @@ +--- +date: 2020-11-09 +id: b4e7d1ee-638f-47ca-b19b-e38ee0c8b142 +title: Symfony user impersonation in debug toolbar +--- + diff --git a/content/wiki/20201109145724-groups_support_for_valid_constraint.md b/content/wiki/20201109145724-groups_support_for_valid_constraint.md new file mode 100644 index 0000000..307e3b7 --- /dev/null +++ b/content/wiki/20201109145724-groups_support_for_valid_constraint.md @@ -0,0 +1,39 @@ +--- +date: 2020-11-09 +id: 5da0c739-af47-49dd-84ea-bb2e48e4a9d8 +title: Groups support for Valid constraint +--- + +# Introduction + +As per [Symfony 4.0](20201109140137-symfony_4_0) validation groups are +supported for the `Valid` constraint. + +# Syntax + +``` php +// src/AppBundle/Entity/Address.php +// ... +class Address +{ + /** @Assert\NotBlank(groups={"basic"}) */ + protected $street; + + /** @Assert\Length(max = 5) */ + protected $zipCode; +} + +// src/AppBundle/Entity/Author.php +// ... +class Author +{ + /** @Assert\NotBlank */ + protected $firstName; + + /** @Assert\NotBlank */ + protected $lastName; + + /** @Assert\Valid(groups={"basic"}) */ + protected $address; +} +``` diff --git a/content/wiki/20201109150109-subscribing_to_events_in_the_micro_kernel.md b/content/wiki/20201109150109-subscribing_to_events_in_the_micro_kernel.md new file mode 100644 index 0000000..eb3320a --- /dev/null +++ b/content/wiki/20201109150109-subscribing_to_events_in_the_micro_kernel.md @@ -0,0 +1,45 @@ +--- +date: 2020-11-09 +id: 6a54254e-2dae-47e5-8966-075e1bc1b7fa +title: Subscribing to events in the micro kernel +--- + +# Introduction + +From [Symfony 4.0](20201109140137-symfony_4_0) it's possible to +subscribe to events using the `EventSubscriberInterface` Interface + +# Syntax + +``` php +// src/Kernel.php +namespace App; + +use App\Exception\DangerException; +use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Kernel as BaseKernel; +use Symfony\Component\HttpKernel\KernelEvents; + +class Kernel extends BaseKernel implements EventSubscriberInterface +{ + use MicroKernelTrait; + + // ... + + public static function getSubscribedEvents() + { + return [KernelEvents::EXCEPTION => 'handleExceptions']; + } + + public function handleExceptions(GetResponseForExceptionEvent $event) + { + if ($event->getException() instanceof DangerException) { + $event->setResponse(Response::create('It\'s dangerous to go alone. Take this ⚔')); + } + + // ... + } +} +``` diff --git a/content/wiki/20201109150640-expression_constraint.md b/content/wiki/20201109150640-expression_constraint.md new file mode 100644 index 0000000..20a80c3 --- /dev/null +++ b/content/wiki/20201109150640-expression_constraint.md @@ -0,0 +1,46 @@ +--- +date: 2020-11-09 +id: 4331b4ee-c987-4e04-8a46-3b8d30e13581 +title: Expression Constraint +--- + +# Syntax + +``` php +use Symfony\Component\Validator\Constraints as Assert; + +class Event +{ + /** @Assert\DateTime() */ + private $startDate; + + /** + * @Assert\DateTime() + * @Assert\Expression("value > this.startDate") + */ + private $endDate; + + // ... +} +``` + +In [Symfony 4.0](20201109140137-symfony_4_0) a new `propertyPath` option +was added: + +``` php +use Symfony\Component\Validator\Constraints as Assert; + +class Event +{ + /** @Assert\DateTime() */ + private $startDate; + + /** + * @Assert\DateTime() + * @Assert\GreaterThan(propertyPath="startDate") + */ + private $endDate; + + // ... +} +``` diff --git a/content/wiki/20201109150640-expressionlanguage_constraint.md b/content/wiki/20201109150640-expressionlanguage_constraint.md new file mode 100644 index 0000000..214d1a4 --- /dev/null +++ b/content/wiki/20201109150640-expressionlanguage_constraint.md @@ -0,0 +1,46 @@ +--- +date: 2020-11-09 +id: cafa5c65-3517-4e04-b724-a7e3b467142d +title: ExpressionLanguage Constraint +--- + +# Syntax + +``` php +use Symfony\Component\Validator\Constraints as Assert; + +class Event +{ + /** @Assert\DateTime() */ + private $startDate; + + /** + * @Assert\DateTime() + * @Assert\Expression("value > this.startDate") + */ + private $endDate; + + // ... +} +``` + +In [Symfony 4.0](20201109140137-symfony_4_0) a new `propertyPath` option +was added: + +``` php +use Symfony\Component\Validator\Constraints as Assert; + +class Event +{ + /** @Assert\DateTime() */ + private $startDate; + + /** + * @Assert\DateTime() + * @Assert\GreaterThan(propertyPath="startDate") + */ + private $endDate; + + // ... +} +``` diff --git a/content/wiki/20201109150950-sessions.md b/content/wiki/20201109150950-sessions.md new file mode 100644 index 0000000..768a5c4 --- /dev/null +++ b/content/wiki/20201109150950-sessions.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-09 +id: bcba1806-dc81-4d8f-9a87-025f1b3b6a23 +title: Sessions +--- + +- [Lazy Sessions](20201109151019-lazy_sessions) +- [Configurable Session ID](20201112125413-configurable_session_id) diff --git a/content/wiki/20201109151019-lazy_sessions.md b/content/wiki/20201109151019-lazy_sessions.md new file mode 100644 index 0000000..7c06ec2 --- /dev/null +++ b/content/wiki/20201109151019-lazy_sessions.md @@ -0,0 +1,25 @@ +--- +date: 2020-11-09 +id: 676f2820-f539-4b0a-8633-668fd0630c3c +title: Lazy Sessions +--- + +# Introduction + +PHP 7.0 introduced a new interface called +`SessionUpdateTimestampHandlerInterface`. As of [Symfony +4.0](20201109140137-symfony_4_0) this has been added to the [PHP7 +Polyfill component](20201109151215-symfony_php7_polyfill_component) + +# Syntax + +``` php +interface SessionUpdateTimestampHandlerInterface +{ + // Checks if a session identifier already exists or not. + public function validateId(string $key) : bool; + + // Updates the timestamp of a session when its data didn't change. + public function updateTimestamp(string $key, string $val) : bool; +} +``` diff --git a/content/wiki/20201109151215-symfony_php7_polyfill_component.md b/content/wiki/20201109151215-symfony_php7_polyfill_component.md new file mode 100644 index 0000000..f1053a9 --- /dev/null +++ b/content/wiki/20201109151215-symfony_php7_polyfill_component.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-09 +id: 5be369cf-363e-4533-839b-bc55ce951a53 +title: Symfony PHP7 Polyfill component +--- + +- [Lazy Sessions](20201109151019-lazy_sessions) diff --git a/content/wiki/20201109151937-debug_autowiring.md b/content/wiki/20201109151937-debug_autowiring.md new file mode 100644 index 0000000..9a3578c --- /dev/null +++ b/content/wiki/20201109151937-debug_autowiring.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-09 +id: 3644daaa-2b31-4ead-b4e1-65ae720cd053 +title: debug autowiring +--- + +Since [Symfony 4.0](20201109140137-symfony_4_0) a dedicated +`debug:autowiring` command has been added to show classes & interfaces +that can be used as type-hints when autowiring. diff --git a/content/wiki/20201109152306-symfony_guard_component.md b/content/wiki/20201109152306-symfony_guard_component.md new file mode 100644 index 0000000..060c012 --- /dev/null +++ b/content/wiki/20201109152306-symfony_guard_component.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-09 +id: 9670dbf7-5195-4da6-b1fe-5a0087bd2940 +title: Symfony Guard Component +--- + +- [getCredentials() responsibilities + split](20201109152527-getcredentials_responsibilities_split) diff --git a/content/wiki/20201109152527-getcredentials_responsibilities_split.md b/content/wiki/20201109152527-getcredentials_responsibilities_split.md new file mode 100644 index 0000000..1bd52ad --- /dev/null +++ b/content/wiki/20201109152527-getcredentials_responsibilities_split.md @@ -0,0 +1,40 @@ +--- +date: 2020-11-09 +id: 9e629f0c-33c0-45bb-a978-623b13b2ffa5 +title: getCredentials() responsibilities split +--- + +Since [Symfony 4.0](20201109140137-symfony_4_0) `getCredentials()` +responsibilities has been split into 2 methods: + +``` php +// BEFORE +use Symfony\Component\Security\Guard\AbstractGuardAuthenticator; + +class TokenAuthenticator extends AbstractGuardAuthenticator +{ + public function getCredentials(Request $request) + { + if (!$token = $request->headers->get('X-AUTH-TOKEN')) { + return null; + } + + return ['token' => $token]; + } +} + +// AFTER +class TokenAuthenticator extends AbstractGuardAuthenticator +{ + public function supports(Request $request) + { + return $request->headers->has('X-AUTH-TOKEN'); + } + + public function getCredentials(Request $request) + { + return ['token' => $request->headers->get('X-AUTH-TOKEN')]; + } +} + +``` diff --git a/content/wiki/20201109152714-debug_form.md b/content/wiki/20201109152714-debug_form.md new file mode 100644 index 0000000..55451ad --- /dev/null +++ b/content/wiki/20201109152714-debug_form.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-09 +id: fa601e70-7a95-4981-b83c-0767b872324e +title: debug form +--- + +This command lists all built-in types, service types, type extensions +and guessers available in your application. Added since [Symfony +4.0](20201109140137-symfony_4_0) diff --git a/content/wiki/20201109152907-symfony_commands.md b/content/wiki/20201109152907-symfony_commands.md new file mode 100644 index 0000000..f0dc88d --- /dev/null +++ b/content/wiki/20201109152907-symfony_commands.md @@ -0,0 +1,14 @@ +--- +date: 2020-11-09 +id: de57051c-69ce-4ffc-80a2-55497308de62 +title: Symfony Commands +--- + +# Linters + +- [lint:yaml](20201116141232-lint_yaml) + +# Debugging + +- [debug:autowiring](20201109151937-debug_autowiring) +- [debug form](20201109152714-debug_form) diff --git a/content/wiki/20201109153159-local_service_binding.md b/content/wiki/20201109153159-local_service_binding.md new file mode 100644 index 0000000..3c94c1c --- /dev/null +++ b/content/wiki/20201109153159-local_service_binding.md @@ -0,0 +1,61 @@ +--- +date: 2020-11-09 +id: 764a4845-b98c-43f6-9b9c-f5b6cc849e7f +title: Local Service Binding +--- + +# Introduction + +Since [Symfony 4.0](20201109140137-symfony_4_0) autowiring scalar +arguments has been simplified with local binding: + +# Syntax + +## Pre Symfony 4.0 + +``` yaml +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + App\Some\Service1: + $projectDir: '%kernel.project_dir%' + + App\Some\Service2: + $projectDir: '%kernel.project_dir%' + + App\Some\Service3: + $projectDir: '%kernel.project_dir%' + +``` + +## Post Symfony 4.0 + +``` yaml +services: + _defaults: + autowire: true + autoconfigure: true + public: false + bind: + $projectDir: '%kernel.project_dir%' + +``` + +## Explicitly define injection services + +``` yaml +# when services created/defined in this file inject 'BarInterface', +# use the '@normal_bar_service' ... +services: + _defaults: + bind: + BarInterface: "@normal_bar_service" + + # ... except for this particular service, which uses a different service + Foo: + bind: + BarInterface: "@special_bar_service" +``` diff --git a/content/wiki/20201110094807-javascript_regexp_s_flag.md b/content/wiki/20201110094807-javascript_regexp_s_flag.md new file mode 100644 index 0000000..629e4be --- /dev/null +++ b/content/wiki/20201110094807-javascript_regexp_s_flag.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-10 +id: 8bf1886a-0754-467f-a441-cb21bccfbd46 +title: JavaScript RegExp /s flag +--- + +# Introduction + +The dot (.) in regular expressions doesn't match line terminator +characters: + +``` javascript +console.log(/%.$/.test('\n')) // false +``` + +The `/s` expression (dotAll) flag fixes this. + +# Syntax + +``` javascript +console.log(/^.$/s.test("\n")); // true +``` diff --git a/content/wiki/20201110095139-javascript_regexp_u_flag.md b/content/wiki/20201110095139-javascript_regexp_u_flag.md new file mode 100644 index 0000000..e5cea02 --- /dev/null +++ b/content/wiki/20201110095139-javascript_regexp_u_flag.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-10 +id: 76fc0a0a-7d56-49c7-8c57-7686cca110fc +title: JavaScript RegExp /u flag +--- + +This flag matches astral characters such as emojis: + +``` javascript +console.log(/^.$/u.test("🙂")); // true +``` diff --git a/content/wiki/20201110100120-php_nullsafe_operator.md b/content/wiki/20201110100120-php_nullsafe_operator.md new file mode 100644 index 0000000..e74e200 --- /dev/null +++ b/content/wiki/20201110100120-php_nullsafe_operator.md @@ -0,0 +1,38 @@ +--- +date: 2020-11-10 +id: d07536b9-8d42-4b60-92a5-0348acb0a3db +title: PHP nullsafe operator +--- + +# Description + +Introduced in [PHP 8.0](20201109133834-php_8_0), nullsafe operators[^1] +enable you to safely use methods that may return `null`. + +# Syntax + +``` php +class bar +{ + public function excellent(): string + { + return "excellent"; + } +} + +class foo +{ + public function getBarOrNull(): ?bar + { + return rand(0, 1) === 1 ? new bar() : null; + } +} + +$foo = new foo(); + +echo $foo->getBarOrNull()?->excellent(); +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110100420-php_attributes.md b/content/wiki/20201110100420-php_attributes.md new file mode 100644 index 0000000..4ba964b --- /dev/null +++ b/content/wiki/20201110100420-php_attributes.md @@ -0,0 +1,50 @@ +--- +date: 2020-11-10 +id: 046ba725-37b9-4aca-837c-5d0cda679cc2 +title: PHP Attributes +--- + +# Description + +Introduced in [PHP 8.0](20201109133834-php_8_0). Attributes[^1] are a +way to add metadata to classes. Stitcher[^2] has an article that goes in +depth. + +# Syntax + +``` php +use App\Attributes\ExampleAttribute; + +#[ExampleAttribute] +class Foo +{ + #[ExampleAttribute] + public const FOO = 'foo'; + + #[ExampleAttribute] + public $x; + + #[ExampleAttribute] + public function foo(#[ExampleAttribute] $bar) { } +} +``` + +``` php +#[Attribute] +class ExampleAttribute +{ + public $value; + + public function __construct($value) + { + $this->value = $value; + } +} + +``` + +# Footnotes + +[^1]: + +[^2]: diff --git a/content/wiki/20201110101308-php_constructor_property_promotion.md b/content/wiki/20201110101308-php_constructor_property_promotion.md new file mode 100644 index 0000000..c865197 --- /dev/null +++ b/content/wiki/20201110101308-php_constructor_property_promotion.md @@ -0,0 +1,46 @@ +--- +date: 2020-11-10 +id: 19579c31-1dcc-4d11-b2f8-5f9180fa66d3 +title: PHP constructor property promotion +--- + +# Description + +Introduced in [PHP 8.0](20201109133834-php_8_0), constructor property +promotions[^1] add new syntatctic sugar to create value & data transfer +objects. + +# Syntax + +``` php +class Money +{ + public Currency $currency; + + public int $amount; + + public function __construct( + Currency $currency, + int $amount, + ) { + $this->currency = $currency; + $this->amount = $amount; + } +} +``` + +can be replaced with + +``` php +class Money +{ + public function __construct( + public Currency $currency, + public int $amount, + ) {} +} +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110102332-php_static_return_type.md b/content/wiki/20201110102332-php_static_return_type.md new file mode 100644 index 0000000..8928804 --- /dev/null +++ b/content/wiki/20201110102332-php_static_return_type.md @@ -0,0 +1,27 @@ +--- +date: 2020-11-10 +id: b2ffe647-59d6-43a1-9e10-d9a278580284 +title: PHP Static Return Type +--- + +# Description + +Introduced in [PHP 8.0](20201109133834-php_8_0), static return types[^1] +guarantee that a method will return an instance of its object, and not +that of a parent. + +# Syntax + +``` php +class Foo +{ + public function tralala(): static + { + return $this; + } +} +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110102900-php_class_name_literal.md b/content/wiki/20201110102900-php_class_name_literal.md new file mode 100644 index 0000000..0346cd7 --- /dev/null +++ b/content/wiki/20201110102900-php_class_name_literal.md @@ -0,0 +1,21 @@ +--- +date: 2020-11-10 +id: e344631b-61fc-4110-abab-e610ce460854 +title: PHP Class Name Literal +--- + +# Description + +Introduced in [PHP 8.0](20201109133834-php_8_0), class name literals[^1] +is a new alternative to `get_class()` + +# Syntax + +``` php +$foo = new Foo(); +var_dump($foo:class) +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110103409-php_stringable_interface.md b/content/wiki/20201110103409-php_stringable_interface.md new file mode 100644 index 0000000..734a0f6 --- /dev/null +++ b/content/wiki/20201110103409-php_stringable_interface.md @@ -0,0 +1,31 @@ +--- +date: 2020-11-10 +id: f97470da-6833-4ecf-81e2-40dd04f6c2a1 +title: PHP Stringable Interface +--- + +# Description + +Since [PHP 8.0](20201109133834-php_8_0), the stringable interface[^1] is +automatically added to classes that implement the `__toString()` method + +# Syntax + +``` php +class Foo +{ + public function __toString(): string + { + return 'foo'; + } +} + +function bar(string|Stringable $stringable) { /* … */ } + +bar(new Foo()); +bar('abc'); +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110103654-php_weak_maps.md b/content/wiki/20201110103654-php_weak_maps.md new file mode 100644 index 0000000..6e2a8a7 --- /dev/null +++ b/content/wiki/20201110103654-php_weak_maps.md @@ -0,0 +1,32 @@ +--- +date: 2020-11-10 +id: 7cdfd822-29cd-4b53-996f-7e7f618f754a +title: PHP Weak Maps +--- + +# Description + +Weak maps[^1] allow creating a map from objects to arbitrary values +(similar to SplObjectStorage) without preventing the objects that are +used as keys from being garbage collected. If an object key is garbage +collected, it will simply be removed from the map. This will save a lot +of headaches for people writing things like ORMs. + +# Syntax + +``` php +class Foo +{ + private WeakMap $cache; + + public function getSomethingWithCaching(object $obj): object + { + return $this->cache[$obj] + ??= $this->computeSomethingExpensive($obj); + } +} +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110103654-php_weap_maps.md b/content/wiki/20201110103654-php_weap_maps.md new file mode 100644 index 0000000..896840c --- /dev/null +++ b/content/wiki/20201110103654-php_weap_maps.md @@ -0,0 +1,37 @@ +--- +date: 2020-11-10 +id: 954a4b48-f3a5-4ef6-a2ea-93f843250c68 +title: PHP Weap Maps +--- + +# Description + +Weak maps[^1] allow creating a map from objects to arbitrary values +(similar to SplObjectStorage) without preventing the objects that are +used as keys from being garbage collected. If an object key is garbage +collected, it will simply be removed from the map. This will save a lot +of headaches for people writing things like ORMs. + +# Syntax + +``` php +class Foo +{ + private WeakMap $cache; + + public function getSomethingWithCaching(object $obj): object + { + return $this->cache[$obj] + ??= $this->computeSomethingExpensive($obj); + } +} +``` + +# Related + +- [PHP](20201109133720-php) +- [PHP 8.0](20201109133834-php_8_0) + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110152518-symfony_4_1.md b/content/wiki/20201110152518-symfony_4_1.md new file mode 100644 index 0000000..af1e18c --- /dev/null +++ b/content/wiki/20201110152518-symfony_4_1.md @@ -0,0 +1,27 @@ +--- +date: 2020-11-10 +id: 3a34951b-9232-4cb2-a1aa-039f6eb36e01 +title: Symfony 4.1 +--- + +# What's new + +## Password Hashers + +- [Argon2i Password + Hasher](20201110152730-symfony_argon2i_password_hasher) + +## Routing + +- [name~prefix~](20201110153351-name_prefix) +- [Inlined Routing + Configuration](20201110154229-inlined_routing_configuration) +- [Internationalized + Routing](20201110154548-internationalized_routing) + +## Components + +### Workflow Component + +- [Workflow PlanetUML format + dump](20201110154017-workflow_planetuml_format_dump) diff --git a/content/wiki/20201110152627-symfony_components.md b/content/wiki/20201110152627-symfony_components.md new file mode 100644 index 0000000..d1e3e9d --- /dev/null +++ b/content/wiki/20201110152627-symfony_components.md @@ -0,0 +1,32 @@ +--- +date: 2020-11-10 +id: 534272ec-1634-40e9-953e-b1e683805239 +title: Symfony Components +--- + +# Components + +- [Console Component](20201109141325-symfony_console_component) +- [Contracts Component](20201116140847-symfony_contracts_component) +- [ExpressionLanguage + Component](20201116135741-expressionlanguage_component) +- [Filesystem Component](20201116142023-filesystem_component) +- [Guard Component](20201109152306-symfony_guard_component) +- [HttpClient Component](20201112140448-httpclient_component) +- [HttpFoundation Component](20201113182438-httpfoundation_component) +- [Mailer Component](20201112135249-mailer_component) +- [Mime Component](20201112140650-mime_component) +- [OptionsResolver + Component](20201116142601-optionsresolver_component) +- [RateLimiter + Component](20201117113404-symfony_ratelimiter_component) +- [Serializer Component](20201111112055-symfony_serializer_component) +- [Stopwatch Component](20201109140848-symfony_stopwatch_component) +- [Symfony String Component](20201113183442-symfony_string_component) +- [Translation + Component](20201109142805-symfony_translation_component) +- [UUID Component](20201116131815-symfony_uuid_component) +- [VarExporter + Component](20201111103442-symfony_varexporter_component) +- [Workflow Component](20201110153611-symfony_workflow_component) +- [String Component](20201113183442-string_component) diff --git a/content/wiki/20201110152730-symfony_argon2i_password_hasher.md b/content/wiki/20201110152730-symfony_argon2i_password_hasher.md new file mode 100644 index 0000000..dc9b2ea --- /dev/null +++ b/content/wiki/20201110152730-symfony_argon2i_password_hasher.md @@ -0,0 +1,36 @@ +--- +date: 2020-11-10 +id: 7cc0b66c-a7df-48c7-9caf-f934f159112d +title: Symfony Argon2i Password Hasher +--- + +# IMPORTANT + +Deprecated in [Symfony 4.3](20201112120118-symfony_4_3) and replaced +with [Sodium password +encoder](20201112133736-sodium_password_encoder)!!! + +# Introduction + +Added in [Symfony 4.1](20201110152518-symfony_4_1), +[Symfony](20201109140300-symfony) now supports Argon[^1] password +hashes. + +# Syntax + +``` yaml +# config/packages/security.yaml +security: + # ... + encoders: + App\Entity\User: + algorithm: "argon2i" + # maximum memory (in KiB) that may be used to compute the Argon2 hash + memory_cost: 1024 + # number of times the Argon2 hash algorithm will be run + time_cost: 3 +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110153351-name_prefix.md b/content/wiki/20201110153351-name_prefix.md new file mode 100644 index 0000000..0dd050e --- /dev/null +++ b/content/wiki/20201110153351-name_prefix.md @@ -0,0 +1,24 @@ +--- +date: 2020-11-10 +id: 1f8217e5-4006-4f7e-9d67-2c68b70b2872 +title: name~prefix~ +--- + +# Introduction + +This is an option to prefix the named of the routes imported in +configuration files. + +# Syntax + +``` yaml +app: + resource: ../controller/routing.yaml + +api: + resource: ../controller/routing.yaml + # this prefix is added to all the action route names + name_prefix: api_ + # this prefix is added to all the action URLs + prefix: /api +``` diff --git a/content/wiki/20201110153611-symfony_workflow_component.md b/content/wiki/20201110153611-symfony_workflow_component.md new file mode 100644 index 0000000..9a95a84 --- /dev/null +++ b/content/wiki/20201110153611-symfony_workflow_component.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-10 +id: 2c91e447-6c2f-4e69-b2d7-204538e3ac98 +title: Symfony Workflow Component +--- + +# Commands + +- [Workflow DOT format dump](20201110153948-workflow_dot_format_dump) +- [Workflow PlanetUML format + dump](20201110154017-workflow_planetuml_format_dump) diff --git a/content/wiki/20201110153948-workflow_dot_format_dump.md b/content/wiki/20201110153948-workflow_dot_format_dump.md new file mode 100644 index 0000000..8dfd841 --- /dev/null +++ b/content/wiki/20201110153948-workflow_dot_format_dump.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-10 +id: 702be5e1-97cc-46df-80fd-7fa96d3e6410 +title: Workflow DOT format dump +--- + +``` shell +bin/console workflow:dump my_workflow | dot -Tpng > my_workflow.png +``` diff --git a/content/wiki/20201110154017-workflow_planetuml_format_dump.md b/content/wiki/20201110154017-workflow_planetuml_format_dump.md new file mode 100644 index 0000000..ede3cf1 --- /dev/null +++ b/content/wiki/20201110154017-workflow_planetuml_format_dump.md @@ -0,0 +1,16 @@ +--- +date: 2020-11-10 +id: 507ab1e2-2e03-4ce1-abfd-91157b681558 +title: Workflow PlanetUML format dump +--- + +In [Symfony 4.1](20201110152518-symfony_4_1) new commands were added to +export to the PlanetUML[^1] format: + +``` shell +bin/console workflow:dump my_workflow --dump-format=puml | java -jar plantuml.jar -p > my_workflow.png +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201110154229-inlined_routing_configuration.md b/content/wiki/20201110154229-inlined_routing_configuration.md new file mode 100644 index 0000000..1378d13 --- /dev/null +++ b/content/wiki/20201110154229-inlined_routing_configuration.md @@ -0,0 +1,40 @@ +--- +date: 2020-11-10 +id: e85e1d41-4327-4a38-b4f9-205e7ccec209 +title: Inlined Routing Configuration +--- + +# Introduction + +Added in [Symfony 4.1](20201110152518-symfony_4_1), inlined routing +configuration allows us to define requirements and default values for +route placeholders. + +# Syntax + +``` php +use Symfony\Component\Routing\Annotation\Route; + +class BlogController extends Controller +{ + /** + * @Route("/blog/{page}", name="blog_list", requirements={"page"="\d+"}, defaults={"page"="1"}) + */ + public function list($page) + { + // ... + } +} +``` + +is now + +``` php +/** + * @Route("/blog/{page<\d+>?1}", name="blog_list") + */ +public function list($page) +{ + // ... +} +``` diff --git a/content/wiki/20201110154548-internationalized_routing.md b/content/wiki/20201110154548-internationalized_routing.md new file mode 100644 index 0000000..e7d6169 --- /dev/null +++ b/content/wiki/20201110154548-internationalized_routing.md @@ -0,0 +1,80 @@ +--- +date: 2020-11-10 +id: 134b2b51-df83-4762-a6e8-335d74f0b3f9 +title: Internationalized Routing +--- + +# Introduction + +Since [Symfony 4.1](20201110152518-symfony_4_1) support for +internationalized routes was added. + +# Syntax + +``` yaml +contact: + controller: App\Controller\ContactController::send + path: + en: /send-us-an-email + nl: /stuur-ons-een-email +``` + +``` php +use Symfony\Component\Routing\Annotation\Route; + +class ContactController +{ + /** + * @Route({ + * "en": "/send-us-an-email", + * "nl": "/stuur-ons-een-email" + * }, name="contact") + */ + public function send() + { + // ... + } +} +``` + +``` php +/** @var UrlGeneratorInterface $urlGenerator */ +// uses the current request locale +$url = $urlGenerator->generate('contact'); + +// ignores the current request locale and generates '/stuur-ons-een-email' +$url = $urlGenerator->generate('contact', ['_locale' => 'nl']); +// this would also work, but it's not recommended: +// $url = $urlGenerator->generate('contact.nl'); +``` + +``` yaml +# config/routes/annotations.yaml +site: + resource: '../src/Controller/' + type: annotation + prefix: + en: '/site' + es: '/sitio' +``` + +``` php +class DefaultController extends Controller +{ + /** + * @Route({"en": "/contact", "es": "/contacto"}, name="contact") + */ + public function contact() + { + // ... + } + + /** + * @Route("/page/{slug}", name="page") + */ + public function page($slug) + { + // ... + } +} +``` diff --git a/content/wiki/20201111092510-javascript_strict_mode.md b/content/wiki/20201111092510-javascript_strict_mode.md new file mode 100644 index 0000000..67a6aad --- /dev/null +++ b/content/wiki/20201111092510-javascript_strict_mode.md @@ -0,0 +1,42 @@ +--- +date: 2020-11-11 +id: c5fef6b1-c659-42ef-8b51-7657df6743e8 +title: JavaScript Strict Mode +--- + +# Description + +[Strict +mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) +makes several changes to normal JavaScript semantics: + +- Eliminates some JavaScript silent errors by changing them to throw + errors. +- Fixes mistakes that make it difficult for JavaScript engines to + perform optimizations: strict mode code can sometimes be made to run + faster than identical code that's not strict mode. +- Prohibits some syntax likely to be defined in future versions of + ECMAScript. + +``` javascript +function canYouSpotTheProblem() { + "use strict"; + for (counter = 0; counter < 10; counter++) { + console.log("Happy happy"); + } +} + +canYouSpotTheProblem(); +// → ReferenceError: counter is not defined +``` + +In strict mode the \`this\` binding holds the value \`undefined\` in +functions that are not called as methods: + +``` javascript +"use strict"; + +function doSomething() { + console.log(this) +} +``` diff --git a/content/wiki/20201111092905-javascript_exceptions.md b/content/wiki/20201111092905-javascript_exceptions.md new file mode 100644 index 0000000..e7d4b0b --- /dev/null +++ b/content/wiki/20201111092905-javascript_exceptions.md @@ -0,0 +1,43 @@ +--- +date: 2020-11-11 +id: 44e4d5c4-ea16-4417-a8e8-5036d3fdd370 +title: JavaScript Exceptions +--- + +# Introduction + +[JavaScript](20200613170905-javascript) supports exceptions. + +# Syntax + +``` javascript +function promptDirection(question) { + let result = prompt(question); + if (result.toLowerCase() == "left") return "L"; + if (result.toLowerCase() == "right") return "R"; + throw new Error("Invalid direction: " + result); +} + +function look() { + if (promptDirection("Which way?") == "L") { + return "a house"; + } else { + return "two angry bears"; + } +} + +try { + console.log("You see", look()); +} catch (error) { + console.log("Something went wrong: " + error); +} +``` + +# See also + +- [Error Sub Types](20201111093101-javascript_error_sub_types) +- [Custom Error Types](20201111093651-javascript_custom_error_types) +- [Finally](20201111094033-javascript_exceptions_finally) +- [JavaScript Error Handling](20200901105237-error_handling) +- [JavaScript](20200613170905-javascript) +- [JavaScript Catch Binding](20201116154444-javascript_catch_binding) diff --git a/content/wiki/20201111093101-javascript_error_sub_types.md b/content/wiki/20201111093101-javascript_error_sub_types.md new file mode 100644 index 0000000..6a76f39 --- /dev/null +++ b/content/wiki/20201111093101-javascript_error_sub_types.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-11 +id: ee97bef0-7d38-4911-a2ce-a9741572d162 +title: JavaScript Error Sub Types +--- + +- [RangeError](20201111093227-javascript_rangeerror) +- [ReferenceError](20201111093310-javascript_referenceerror) +- [SyntaxError](20201111093338-javascript_syntaxerror) +- [TypeError](20201111093400-javascript_typeerror) +- [UriError](20201111093418-javascript_urierror) diff --git a/content/wiki/20201111093227-javascript_rangeerror.md b/content/wiki/20201111093227-javascript_rangeerror.md new file mode 100644 index 0000000..64f867d --- /dev/null +++ b/content/wiki/20201111093227-javascript_rangeerror.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-11 +id: 67198605-05a4-4a1b-9083-d4e445b38344 +title: JavaScript RangeError +--- + +``` javascript +// Call console with too many arguments +console.log.apply(console, new Array(1000000000)); // RangeError: Invalid array length +``` diff --git a/content/wiki/20201111093310-javascript_referenceerror.md b/content/wiki/20201111093310-javascript_referenceerror.md new file mode 100644 index 0000000..bf900c0 --- /dev/null +++ b/content/wiki/20201111093310-javascript_referenceerror.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-11 +id: 52bd8a6a-0d4c-4860-b015-333e7f1b7e34 +title: JavaScript ReferenceError +--- + +``` javascript +'use strict'; +console.log(notValidVar); // ReferenceError: notValidVar is not defined +``` diff --git a/content/wiki/20201111093338-javascript_syntaxerror.md b/content/wiki/20201111093338-javascript_syntaxerror.md new file mode 100644 index 0000000..7734d2a --- /dev/null +++ b/content/wiki/20201111093338-javascript_syntaxerror.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-11 +id: e82c3aab-ac64-4d7e-bafe-79b424a1e2fd +title: JavaScript SyntaxError +--- + +``` typescript +1***3; // SyntaxError: Unexpected token * +``` diff --git a/content/wiki/20201111093400-javascript_typeerror.md b/content/wiki/20201111093400-javascript_typeerror.md new file mode 100644 index 0000000..7e6a992 --- /dev/null +++ b/content/wiki/20201111093400-javascript_typeerror.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-11 +id: b7195c0a-eafb-40e6-803f-8a25a06b6658 +title: JavaScript TypeError +--- + +## TypeError + +``` javascript +('1.2').toPrecision(1); // TypeError: '1.2'.toPrecision is not a function +``` diff --git a/content/wiki/20201111093418-javascript_urierror.md b/content/wiki/20201111093418-javascript_urierror.md new file mode 100644 index 0000000..a629d93 --- /dev/null +++ b/content/wiki/20201111093418-javascript_urierror.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-11 +id: 8bfc6467-46c6-40c6-8a5e-44c296b2a988 +title: JavaScript UriError +--- + +``` javascript +decodeURI('%'); // URIError: URI malformed +``` diff --git a/content/wiki/20201111093651-javascript_custom_error_types.md b/content/wiki/20201111093651-javascript_custom_error_types.md new file mode 100644 index 0000000..05c0625 --- /dev/null +++ b/content/wiki/20201111093651-javascript_custom_error_types.md @@ -0,0 +1,31 @@ +--- +date: 2020-11-11 +id: ce0d13cd-6680-4415-b375-c22de367cb21 +title: JavaScript Custom Error Types +--- + +# Introduction + +Introduced in [ES6](20201030093404-es6), +[JavaScript](20200613170905-javascript) allows you to create your own +custom error objects. + +# Syntax + +``` javascript +class MyError extends Error {} + +function tralala() { + throw new MyError("blahblahblah") +} + +try { + tralala() +} catch (e) { + if (e instanceof MyError) { + console.log("Something went wrong with tralala"); + } else { + throw e; + } +} +``` diff --git a/content/wiki/20201111094033-javascript_exceptions_finally.md b/content/wiki/20201111094033-javascript_exceptions_finally.md new file mode 100644 index 0000000..517a5de --- /dev/null +++ b/content/wiki/20201111094033-javascript_exceptions_finally.md @@ -0,0 +1,37 @@ +--- +date: 2020-11-11 +id: 06ffac8f-e131-4a17-8c88-7edbe3bd0cfd +title: JavaScript Exceptions Finally +--- + +# Description + +Code in `finally` block is **always** run after code in the `try` block: + +# Syntax + +``` javascript +function baSays() { + throw new Error("I pity the fool!") +} + +try { + baSays() +} catch (error) { + console.log("This is the B.A. error: " + error) +} finally { + console.log("This code is always run!") +} + +function hannibalSays() { + console.log("I love it when a plan comes together!") +} + +try { + hannibalSays() +} catch (error) { + console.log("This is the Hannibal error: " + error) +} finally { + console.log("This code is always run!") +} +``` diff --git a/content/wiki/20201111094957-executing_promises_in_parallel.md b/content/wiki/20201111094957-executing_promises_in_parallel.md new file mode 100644 index 0000000..05668bf --- /dev/null +++ b/content/wiki/20201111094957-executing_promises_in_parallel.md @@ -0,0 +1,17 @@ +--- +date: 2020-11-11 +id: 9c42715a-8324-4570-ab92-927b608aa02a +title: Executing Promises in Parallel +--- + +``` javascript +Promise.all([ + asyncFunc1(), + asyncFunc2(), +]) +.then(([result1, result2]) => { +}) +.catch(err => { + // Receives first rejection among the Promises +}); +``` diff --git a/content/wiki/20201111094957-executing_promises_in_parallel_promises_all.md b/content/wiki/20201111094957-executing_promises_in_parallel_promises_all.md new file mode 100644 index 0000000..d276e06 --- /dev/null +++ b/content/wiki/20201111094957-executing_promises_in_parallel_promises_all.md @@ -0,0 +1,25 @@ +--- +date: 2020-11-11 +id: fe95210e-f59a-45a4-b0ed-f4d3ec981a07 +title: Executing Promises in Parallel (Promises.all) +--- + +# Description + +Run promises in parallel. Will throw an +[exception](20201111092905-javascript_exceptions) if one of the requests +fail. + +# Syntax + +``` javascript +Promise.all([ + asyncFunc1(), + asyncFunc2(), +]) +.then(([result1, result2]) => { +}) +.catch(err => { + // Receives first rejection among the Promises +}); +``` diff --git a/content/wiki/20201111095100-catching_promise_errors.md b/content/wiki/20201111095100-catching_promise_errors.md new file mode 100644 index 0000000..2a0d666 --- /dev/null +++ b/content/wiki/20201111095100-catching_promise_errors.md @@ -0,0 +1,17 @@ +--- +date: 2020-11-11 +id: af9d9cf2-a888-4e8e-8156-4c4a664450f1 +title: Catching Promise Errors +--- + +# Syntax + +``` javascript +new Promise((_, reject) => reject(new Error("Fail"))) + .then(value => console.log("Handler 1")) + .catch(reason => { + console.log("Caught failure " + reason); + return "nothing"; + }) + .then(value => console.log("Handler 2", value)); +``` diff --git a/content/wiki/20201111095230-javascript_producing_promises.md b/content/wiki/20201111095230-javascript_producing_promises.md new file mode 100644 index 0000000..e8667f2 --- /dev/null +++ b/content/wiki/20201111095230-javascript_producing_promises.md @@ -0,0 +1,27 @@ +--- +date: 2020-11-11 +id: 1cd276d1-1af0-4472-aec6-bfd148cb5361 +title: JavaScript Producing Promises +--- + +# Advice + +Use [Async functions](20201026103714-javascript_async_functions) instead +of this. + +# Syntax + +``` javascript +const p = new Promise( + function (resolve, reject) { // (A) + if (true /* replace true with your own logic */) { + resolve(value); // success + } else { + reject(reason); // failure + } + }); +``` + +# Related + +- [JavaScript Promises](20200911154351-promises) diff --git a/content/wiki/20201111095230-producing_promises.md b/content/wiki/20201111095230-producing_promises.md new file mode 100644 index 0000000..aa305e5 --- /dev/null +++ b/content/wiki/20201111095230-producing_promises.md @@ -0,0 +1,23 @@ +--- +date: 2020-11-11 +id: e059aba7-2912-4a54-8c04-dbb6fbd3d0a7 +title: Producing Promises +--- + +# Advice + +Use [Async functions](20201026103714-javascript_async_functions) instead +of this. + +# Syntax + +``` javascript +const p = new Promise( + function (resolve, reject) { // (A) + if (true /* replace true with your own logic */) { + resolve(value); // success + } else { + reject(reason); // failure + } + }); +``` diff --git a/content/wiki/20201111095316-javascript_consuming_promises.md b/content/wiki/20201111095316-javascript_consuming_promises.md new file mode 100644 index 0000000..cdc9980 --- /dev/null +++ b/content/wiki/20201111095316-javascript_consuming_promises.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-11 +id: 5280d3db-1858-4b6c-82d7-6a5d5bf5d5c6 +title: JavaScript Consuming Promises +--- + +# Advice + +Use [Async functions](20201026103714-javascript_async_functions) instead +of this. + +# Syntax + +``` javascript +promise +.then(value => { /* fulfillment */ }) +.catch(error => { /* rejection */ }); +``` diff --git a/content/wiki/20201111095454-javascript_promises_finally.md b/content/wiki/20201111095454-javascript_promises_finally.md new file mode 100644 index 0000000..b4f6062 --- /dev/null +++ b/content/wiki/20201111095454-javascript_promises_finally.md @@ -0,0 +1,39 @@ +--- +date: 2020-11-11 +id: 189b65a7-906f-41fd-91cd-57c4cc5764d2 +title: JavaScript Promises Finally +--- + +# Introduction + +Like [Exceptions](20201111094033-javascript_exceptions_finally), since +[ES2018](20201030095105-es2018) JavaScript +[Promises](20200911154351-promises) also support `.finally()`. + +# Syntax + +``` javascript +promise + .then((result) => {}) + .catch((error) => {}) + .finally(() => {}); +``` + +## Shorthand + +``` javascript +promise.finally(() => {}); +``` + +is equal to + +``` javascript +promise.then( + (result) => { + return result; + }, + (error) => { + throw error; + } +); +``` diff --git a/content/wiki/20201111100807-php_throw_expression.md b/content/wiki/20201111100807-php_throw_expression.md new file mode 100644 index 0000000..5ae01c2 --- /dev/null +++ b/content/wiki/20201111100807-php_throw_expression.md @@ -0,0 +1,37 @@ +--- +date: 2020-11-11 +id: d4bcfd55-088e-4658-9e7b-5429f7ec060f +title: PHP Throw Expression +--- + +# Description + +Since [PHP 8.0](20201109133834-php_8_0), `throw` can also be used as an +expression[^1]. + +# Syntax + +``` php +// This was previously not possible since arrow functions only accept a single expression while throw was a statement. +$callable = fn() => throw new Exception(); + +// $value is non-nullable. +$value = $nullableValue ?? throw new InvalidArgumentException(); + +// $value is truthy. +$value = $falsableValue ?: throw new InvalidArgumentException(); + +// $value is only set if the array is not empty. +$value = !empty($array) + ? reset($array) + : throw new InvalidArgumentException(); + +$condition && throw new Exception(); +$condition || throw new Exception(); +$condition and throw new Exception(); +$condition or throw new Exception(); +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201111101148-php_non_capturing_catches.md b/content/wiki/20201111101148-php_non_capturing_catches.md new file mode 100644 index 0000000..b3f6811 --- /dev/null +++ b/content/wiki/20201111101148-php_non_capturing_catches.md @@ -0,0 +1,36 @@ +--- +date: 2020-11-11 +id: 1c3522c3-9c66-4e10-bf2d-e01807707af2 +title: PHP Non-capturing Catches +--- + +# Description + +Since [PHP 8.0](20201109133834-php_8_0), exceptions are allowed without +capturing them into variables[^1]. + +# Syntax + +## Pre PHP8 + +``` php +try { + changeImportantData(); +} catch (PermissionException $ex) { + echo "You don't have permission to do this"; +} +``` + +## Post PHP8 + +``` php +try { + changeImportantData(); +} catch (PermissionException) { // The intention is clear: exception details are irrelevant + echo "You don't have permission to do this"; +} +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201111101706-symfony_4_2.md b/content/wiki/20201111101706-symfony_4_2.md new file mode 100644 index 0000000..da87070 --- /dev/null +++ b/content/wiki/20201111101706-symfony_4_2.md @@ -0,0 +1,43 @@ +--- +date: 2020-11-11 +id: 359db499-56d9-4b77-b7cb-81b76616e6e7 +title: Symfony 4.2 +--- + +# What's new + +## Constraints + +- [DivisibleBy + Constraint](20201111103048-symfony_divisibleby_constraint) + +## Components + +### VarExporter + +- [VarExporter + Component](20201111103442-symfony_varexporter_component) + +### Console + +- [Table Titles](20201111104124-syfmony_console_table_titles) + +### Autowiring + +- [Autowiring By Type and + Name](20201111104814-autowiring_by_type_and_name) + +### Forms + +- [Clear Form Errors](20201111105422-symfony_clear_form_errors) + +### Routing + +- [Fallback For Internationalized + Routes](20201111111636-fallback_for_internationalized_routes) + +### Serializer + +1. Annotations + + - [@SerializedName](20201111112247-serializedname) diff --git a/content/wiki/20201111103048-symfony_divisibleby_constraint.md b/content/wiki/20201111103048-symfony_divisibleby_constraint.md new file mode 100644 index 0000000..0039bf4 --- /dev/null +++ b/content/wiki/20201111103048-symfony_divisibleby_constraint.md @@ -0,0 +1,34 @@ +--- +date: 2020-11-11 +id: 5cc7016f-2142-47c3-b256-d295a58339a7 +title: Symfony DivisibleBy Constraint +--- + +# Introduction + +Introduced in [Symfony 4.2](20201111101706-symfony_4_2), `DivisibleBy` +enforces specific increments on a number. + +# Syntax + +``` php +// src/Entity/Item.php +namespace App\Entity; +use Symfony\Component\Validator\Constraints as Assert; + +class Item +{ + /** + * @Assert\DivisibleBy(0.25) + */ + protected $weight; + + /** + * @Assert\DivisibleBy( + * value = 5, + * message = "This item requires to be stocked in multiples of 5 units." + * ) + */ + protected $quantity; +} +``` diff --git a/content/wiki/20201111103442-symfony_varexporter_component.md b/content/wiki/20201111103442-symfony_varexporter_component.md new file mode 100644 index 0000000..09df7af --- /dev/null +++ b/content/wiki/20201111103442-symfony_varexporter_component.md @@ -0,0 +1,75 @@ +--- +date: 2020-11-11 +id: a334a0bb-a462-4e8f-94df-6a9985a2c5e3 +title: Symfony VarExporter Component +--- + +# Introduction + +Introduced in [Symfony 4.2](20201111101706-symfony_4_2), the VarExporter +Component is a better alternative to PHP's `var_export()` function. The +`var_export()` function outputs or returns a parsable string +representation of a variable. It is similar to `var_dump()` with one +exception: the returned representation is valid PHP code. Symfony's +`export()` function is similar, but adds lots of useful features to it. + +# Syntax + +## Array + +``` php +$data = array(123, array('abc')); +$result = VarExporter::export($data); +``` + +generates + +``` php +setHeaderTitle('Books') + ->setFooterTitle('Page 1/2') + ->setHeaders(['ISBN', 'Title', 'Author']) + ->setRows([ + ['99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'], + // ... + ]) +; +$table->render(); +``` + +## Set max column width + +``` php +// ... + +// the first argument is the column position (starting from 0) and +// the second argument is the max length in characters +$table->setColumnMaxWidth(0, 5); +$table->setColumnMaxWidth(1, 10); +$table->render(); +``` diff --git a/content/wiki/20201111104814-autowiring_by_type_and_name.md b/content/wiki/20201111104814-autowiring_by_type_and_name.md new file mode 100644 index 0000000..ed30580 --- /dev/null +++ b/content/wiki/20201111104814-autowiring_by_type_and_name.md @@ -0,0 +1,24 @@ +--- +date: 2020-11-11 +id: 5d2da6a0-e612-41f3-9ac7-756a541dc8e8 +title: Autowiring By Type and Name +--- + +# Introduction + +Since [Symfony 4.2](20201111101706-symfony_4_2), services can now be +bound by type and name. + +# Syntax + +``` yaml +# config/services.yaml +services: + _defaults: + bind: + # it works with scalar types too (string, int, array, etc.) + string $adminEmail: 'manager@example.com' + + # but it's mostly used with classes + Psr\Log\LoggerInterface $requestLogger: '@monolog.logger.request' +``` diff --git a/content/wiki/20201111105422-symfony_clear_form_errors.md b/content/wiki/20201111105422-symfony_clear_form_errors.md new file mode 100644 index 0000000..a3b5468 --- /dev/null +++ b/content/wiki/20201111105422-symfony_clear_form_errors.md @@ -0,0 +1,25 @@ +--- +date: 2020-11-11 +id: 6e924661-5376-459d-9365-0054027c1755 +title: Symfony Clear Form Errors +--- + +# Introduction + +Introduced in [Symfony 4.2](20201111101706-symfony_4_2), `clearErrors()` +allows us to remove any existing errors in forms. Some user cases: + +- Partial form submissions with AJAX + +# Syntax + +``` php +$task ={}; +$form = $this->createForm(TaskType::class, $task); +// ... + +$form->clearErrors(); + +// this removes errors from the form and all its children forms +$form->clearErrors(true); +``` diff --git a/content/wiki/20201111111255-symfony_autowiring.md b/content/wiki/20201111111255-symfony_autowiring.md new file mode 100644 index 0000000..32dd83e --- /dev/null +++ b/content/wiki/20201111111255-symfony_autowiring.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-11 +id: 470b2f08-e50c-4ec4-8d42-dd369ea1fbb1 +title: Symfony Autowiring +--- + +- [Local Service Binding](20201109153159-local_service_binding) +- [Autowiring By Type and + Name](20201111104814-autowiring_by_type_and_name) +- [Configuring Services With Immutable + Setters](20201112131310-configuring_services_with_immutable_setters) + +# Annotations + +- [@required](20201117112017-required) + +# Commands + +- [debug autowiring](20201109151937-debug_autowiring) diff --git a/content/wiki/20201111111636-fallback_for_internationalized_routes.md b/content/wiki/20201111111636-fallback_for_internationalized_routes.md new file mode 100644 index 0000000..156e6a5 --- /dev/null +++ b/content/wiki/20201111111636-fallback_for_internationalized_routes.md @@ -0,0 +1,39 @@ +--- +date: 2020-11-11 +id: 2b3fbe1c-487f-40e0-88aa-a1b6d59093e3 +title: Fallback For Internationalized Routes +--- + +# Introduction + +Since [Symfony 4.2](20201111101706-symfony_4_2), it's possible to define +internationalized +[routes](20201111111636-fallback_for_internationalized_routes) without +the region part. [Symfony](20201109140300-symfony) will match them +ignoring the region part of the locacle. + +# Syntax + +``` php +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route({ "en_GB": "/about-us", "en_US": "/about-us" }, name="about") + */ +public function about() +{ + // ... +} +``` + +can now be defined as + +``` php +/** + * @Route({ "en": "/about-us" }, name="about") + */ +public function about() +{ + // ... +} +``` diff --git a/content/wiki/20201111112055-symfony_serializer_component.md b/content/wiki/20201111112055-symfony_serializer_component.md new file mode 100644 index 0000000..af842c1 --- /dev/null +++ b/content/wiki/20201111112055-symfony_serializer_component.md @@ -0,0 +1,14 @@ +--- +date: 2020-11-11 +id: 2e18b539-ef55-4c6a-9305-aa61cf31c6b8 +title: Symfony Serializer Component +--- + +# Annotations + +- [@Ignore](20201116140434-ignore) +- [@SerializedName](20201111112247-serializedname) + +# Normalizers + +- [UUID Normalizer](20201117103957-uuid_normalizer) diff --git a/content/wiki/20201111112247-serializedname.md b/content/wiki/20201111112247-serializedname.md new file mode 100644 index 0000000..76934e6 --- /dev/null +++ b/content/wiki/20201111112247-serializedname.md @@ -0,0 +1,31 @@ +--- +date: 2020-11-11 +id: b4612276-2244-4ad6-b3cd-f7e59a2da999 +title: "@SerializedName" +--- + +# Introduction + +From [Symfony 4.2](20201111101706-symfony_4_2), it's possible to +configure name conversion rules using metadata. + +# Syntax + +``` php +namespace App\Entity; + +use Symfony\Component\Serializer\Annotation\SerializedName; + +class Person +{ + /** @SerializedName("customer_name") */ + private $firstName; + + public function __construct(string $firstName) + { + $this->firstName = $firstName; + } + + // ... +} +``` diff --git a/content/wiki/20201112095341-javascript_string_prototype_methods.md b/content/wiki/20201112095341-javascript_string_prototype_methods.md new file mode 100644 index 0000000..c4b5e17 --- /dev/null +++ b/content/wiki/20201112095341-javascript_string_prototype_methods.md @@ -0,0 +1,17 @@ +--- +date: 2020-11-12 +id: 0fb73f75-ee10-4f7d-a7ab-7cac825aaa32 +title: JavaScript String Prototype Methods +--- + +# Methods + +- [endsWith](20201112095428-javascript_string_endswith_method) +- [includes](20201112095504-javascript_string_includes_method) +- [padEnd](20201112095711-javascript_string_padend_method) +- [padStart](20201112095657-javascript_string_padstart_method) +- [repeat](20201112095451-javascript_string_repeat_method) +- [startsWith](20201112095525-javascript_string_startswith_method) +- [trim](20201116100345-trim) +- [trimEnd](20201116100239-trimend) +- [trimStart](20201116100205-trimstart) diff --git a/content/wiki/20201112095428-javascript_string_endswith_method.md b/content/wiki/20201112095428-javascript_string_endswith_method.md new file mode 100644 index 0000000..5cc0751 --- /dev/null +++ b/content/wiki/20201112095428-javascript_string_endswith_method.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-12 +id: 00b0d7a6-4222-47e3-a0c9-58f071fa404e +title: JavaScript String endsWith Method +--- + +# Introduction + +Introduced in [ES6](20201030093404-es6) + +# Syntax + +``` javascript +console.log('hello'.endsWith('ello')) // true +console.log('hello'.endsWith('ello', 5)) // true +``` + +# See also + +- [startsWith](20201112095525-javascript_string_startswith_method) +- [JavaScript String Prototype + Methods](20201112095341-javascript_string_prototype_methods) diff --git a/content/wiki/20201112095451-javascript_string_repeat_method.md b/content/wiki/20201112095451-javascript_string_repeat_method.md new file mode 100644 index 0000000..6e02f49 --- /dev/null +++ b/content/wiki/20201112095451-javascript_string_repeat_method.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: e3638bb4-1baa-4619-b2b9-283040f14b65 +title: JavaScript String Repeat Method +--- + +# Syntax + +``` javascript +console.log('dodo '.repeat(3)) // dodo dodo dodo +``` diff --git a/content/wiki/20201112095504-javascript_string_includes_method.md b/content/wiki/20201112095504-javascript_string_includes_method.md new file mode 100644 index 0000000..4124af1 --- /dev/null +++ b/content/wiki/20201112095504-javascript_string_includes_method.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-12 +id: da46f6f1-d81f-48f7-9704-fd1f69debb85 +title: JavaScript String includes Method +--- + +# Syntax + +``` javascript +console.log('hello'.includes('ell')) // true +console.log('hello'.includes('ell', 1)) // true +``` diff --git a/content/wiki/20201112095525-javascript_string_startswith_method.md b/content/wiki/20201112095525-javascript_string_startswith_method.md new file mode 100644 index 0000000..41ab0e1 --- /dev/null +++ b/content/wiki/20201112095525-javascript_string_startswith_method.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-12 +id: 8a5acfc2-e49c-4f3a-8823-00d7b57e8569 +title: JavaScript String startsWith Method +--- + +# Syntax + +``` javascript +console.log('hello'.startsWith('hell')) // true +console.log('hello'.startsWith('ell', 1)) // true +``` + +# See also + +- [endsWith](20201112095428-javascript_string_endswith_method) +- [JavaScript String Prototype + Methods](20201112095341-javascript_string_prototype_methods) diff --git a/content/wiki/20201112095657-javascript_string_padstart_method.md b/content/wiki/20201112095657-javascript_string_padstart_method.md new file mode 100644 index 0000000..06e66b2 --- /dev/null +++ b/content/wiki/20201112095657-javascript_string_padstart_method.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: 49a334dd-0103-46cc-abba-af84529fae70 +title: JavaScript String padStart Method +--- + +# Syntax + +``` javascript +console.log("x".padStart(5, "ab")); // ababx +``` diff --git a/content/wiki/20201112095711-javascript_string_padend_method.md b/content/wiki/20201112095711-javascript_string_padend_method.md new file mode 100644 index 0000000..70c0ceb --- /dev/null +++ b/content/wiki/20201112095711-javascript_string_padend_method.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-12 +id: 2ced27fe-8663-43d3-b3e7-f2b332599637 +title: JavaScript String padEnd Method +--- + +# Syntax + +``` javascript +console.log("x".padEnd(5, "ab")); // xabab +``` + +# See also + +- [padStart](20201112095657-javascript_string_padstart_method) +- [JavaScript String Prototype + Methods](20201112095341-javascript_string_prototype_methods) +- [ES2017](20201026104538-es2017) diff --git a/content/wiki/20201112100548-javascript_string_literals.md b/content/wiki/20201112100548-javascript_string_literals.md new file mode 100644 index 0000000..bce3f1f --- /dev/null +++ b/content/wiki/20201112100548-javascript_string_literals.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-12 +id: 923e16d1-33dd-4753-bf51-0e77de10efaa +title: JavaScript String Literals +--- + +- [Template Literals](20201112100637-javascript_template_literals) +- [Tagged Template + Literals](20201112100859-javascript_tagged_template_literals) diff --git a/content/wiki/20201112100637-javascript_template_literals.md b/content/wiki/20201112100637-javascript_template_literals.md new file mode 100644 index 0000000..76b124d --- /dev/null +++ b/content/wiki/20201112100637-javascript_template_literals.md @@ -0,0 +1,23 @@ +--- +date: 2020-11-12 +id: 5ec1f0af-b176-4c10-8490-d732f369ee45 +title: JavaScript Template Literals +--- + +# Description + +Template literals[^1] can span lines and also embed other values. \${} +in a template literal will be computed and converted to a +[string](20200922164551-strings). + +# Syntax + +``` javascript +console.log(`This is a +backtick quotes string`) +console.log(`half of 100 is ${100 / 2}`) +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201112100859-javascript_tagged_template_literals.md b/content/wiki/20201112100859-javascript_tagged_template_literals.md new file mode 100644 index 0000000..aca4080 --- /dev/null +++ b/content/wiki/20201112100859-javascript_tagged_template_literals.md @@ -0,0 +1,42 @@ +--- +date: 2020-11-12 +id: 6e8147d7-6328-4509-ba82-3f906aedf6cf +title: JavaScript Tagged Template Literals +--- + +# Description + +Function calls whose parameters are provided via [template +literals](20201112100637-javascript_template_literals). + +# Syntax + +``` javascript +let person = 'Mike'; +let age = 28; + +function myTag(strings, personExp, ageExp) { + let str0 = strings[0]; // "That " + let str1 = strings[1]; // " is a " + + // There is technically a string after + // the final expression (in our example), + // but it is empty (""), so disregard. + // let str2 = strings[2]; + + let ageStr; + if (ageExp > 99){ + ageStr = 'centenarian'; + } else { + ageStr = 'youngster'; + } + + // We can even return a string built using a template literal + return `${str0}${personExp}${str1}${ageStr}`; +} + +let output = myTag`That ${ person } is a ${ age }`; + +console.log(output); +// That Mike is a youngster +``` diff --git a/content/wiki/20201112101218-javascript_string_escapes.md b/content/wiki/20201112101218-javascript_string_escapes.md new file mode 100644 index 0000000..7d34288 --- /dev/null +++ b/content/wiki/20201112101218-javascript_string_escapes.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-12 +id: 9796dbba-5a4e-4835-82bd-c6a626d5c20e +title: JavaScript String Escapes +--- + +- [Unicode Code Point + Escapes](20201112101432-unicode_code_point_escapes) diff --git a/content/wiki/20201112101432-unicode_code_point_escapes.md b/content/wiki/20201112101432-unicode_code_point_escapes.md new file mode 100644 index 0000000..2a35a5f --- /dev/null +++ b/content/wiki/20201112101432-unicode_code_point_escapes.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: 8beda434-6bd6-4364-96fe-7912bfe062fb +title: Unicode Code Point Escapes +--- + +# Syntax + +``` javascript +console.log('\uD83D\uDE80'); +``` diff --git a/content/wiki/20201112101637-unicode.md b/content/wiki/20201112101637-unicode.md new file mode 100644 index 0000000..d6683be --- /dev/null +++ b/content/wiki/20201112101637-unicode.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-12 +id: a24484c6-ffa7-4419-b8d5-e4723089e2a0 +title: Unicode +--- + +- [Unicode Code Point + Escapes](20201112101432-unicode_code_point_escapes) +- [RegExp Unicode Property + Escapes](20201106090634-javascript_regexp_unicode_property_escapes) diff --git a/content/wiki/20201112101851-javascript_string_iteration.md b/content/wiki/20201112101851-javascript_string_iteration.md new file mode 100644 index 0000000..d771a0c --- /dev/null +++ b/content/wiki/20201112101851-javascript_string_iteration.md @@ -0,0 +1,13 @@ +--- +date: 2020-11-12 +id: ca9793a1-b56c-453c-a564-882ba0bd138b +title: JavaScript String Iteration +--- + +# Syntax + +``` javascript +for (const ch of 'abc') { + console.log(ch); +} +``` diff --git a/content/wiki/20201112102537-javascript_string_to_array_conversion.md b/content/wiki/20201112102537-javascript_string_to_array_conversion.md new file mode 100644 index 0000000..11f71d6 --- /dev/null +++ b/content/wiki/20201112102537-javascript_string_to_array_conversion.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-12 +id: 0efc7236-a6cb-402f-91f6-f05f038a4aa2 +title: JavaScript String To Array Conversion +--- + +# Description + +Strings can be [converted](20200613170756-javascript_type_conversion) +into [arrays](20200826201029-arrays) with the +[spread](20201014094144-spread) operator: + +# Syntax + +``` javascript +const chars = [..."abc"]; +console.log(chars); // Array(3) [ "a", "b", "c" ] +``` diff --git a/content/wiki/20201112103849-javascript_arithmetic_operators.md b/content/wiki/20201112103849-javascript_arithmetic_operators.md new file mode 100644 index 0000000..8a3baa2 --- /dev/null +++ b/content/wiki/20201112103849-javascript_arithmetic_operators.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-12 +id: 58b56604-9283-46c5-bbdc-459778ee11ec +title: JavaScript Arithmetic Operators +--- + +# Operators + +- [Addition Operator](20201112103931-javascript_addition_operator) +- [Subtraction + Operator](20201112104144-javascript_subtraction_operator) +- [Multiplication + Operator](20201112104254-javascript_multiplication_operator) +- [Division Operator](20201112104418-javascript_division_operator) +- [Parenthesis + Operator](20201112104544-javascript_parenthesis_operator) +- [Remainder Operator](20201112104654-javascript_remainder_operator) +- [Exponentation + Operator](20201112110203-javascript_exponentation_operator) diff --git a/content/wiki/20201112103931-javascript_addition_operator.md b/content/wiki/20201112103931-javascript_addition_operator.md new file mode 100644 index 0000000..492dd6c --- /dev/null +++ b/content/wiki/20201112103931-javascript_addition_operator.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: 4226bcc9-90e2-4324-9e72-d38000dacf3a +title: JavaScript Addition Operator +--- + +# Syntax + +``` javascript +console.log(100+4) +``` diff --git a/content/wiki/20201112104144-javascript_subtraction_operator.md b/content/wiki/20201112104144-javascript_subtraction_operator.md new file mode 100644 index 0000000..61d2b78 --- /dev/null +++ b/content/wiki/20201112104144-javascript_subtraction_operator.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: 996c32e9-5c8d-4c90-af71-c28e040eae41 +title: JavaScript Subtraction Operator +--- + +# Syntax + +``` javascript +console.log(100-4) +``` diff --git a/content/wiki/20201112104254-javascript_multiplication_operator.md b/content/wiki/20201112104254-javascript_multiplication_operator.md new file mode 100644 index 0000000..7acd9b7 --- /dev/null +++ b/content/wiki/20201112104254-javascript_multiplication_operator.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: 231df23c-9d12-44fb-a1ee-3f8cb4a788ab +title: JavaScript Multiplication Operator +--- + +# Syntax + +``` javascript +console.log(100*4) +``` diff --git a/content/wiki/20201112104418-javascript_division_operator.md b/content/wiki/20201112104418-javascript_division_operator.md new file mode 100644 index 0000000..8416844 --- /dev/null +++ b/content/wiki/20201112104418-javascript_division_operator.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: f8f0ade7-0624-4155-a430-e3c81fd7d72b +title: JavaScript Division Operator +--- + +# Syntax + +``` javascript +console.log(100/4) +``` diff --git a/content/wiki/20201112104544-javascript_parenthesis_operator.md b/content/wiki/20201112104544-javascript_parenthesis_operator.md new file mode 100644 index 0000000..9546b97 --- /dev/null +++ b/content/wiki/20201112104544-javascript_parenthesis_operator.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: ec5dcb11-0690-442f-b70c-7f64534a5185 +title: JavaScript Parenthesis Operator +--- + +# Sytnax + +``` javascript +console.log((100+4) * 11) // 1144 +``` diff --git a/content/wiki/20201112104654-javascript_remainder_operator.md b/content/wiki/20201112104654-javascript_remainder_operator.md new file mode 100644 index 0000000..f18fc3c --- /dev/null +++ b/content/wiki/20201112104654-javascript_remainder_operator.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: 33f8272d-6dc4-4a12-b384-0a4cdbd2a24a +title: JavaScript Remainder Operator +--- + +# Syntax + +``` javascript +console.log(314 % 100) // 14 +``` diff --git a/content/wiki/20201112104819-javascript_string_operators.md b/content/wiki/20201112104819-javascript_string_operators.md new file mode 100644 index 0000000..b7fcf22 --- /dev/null +++ b/content/wiki/20201112104819-javascript_string_operators.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-12 +id: 16729463-8ac7-4389-8558-cf243066aa42 +title: JavaScript String Operators +--- + +# Operators + +- [Concatenation + Operator](20201112104934-javascript_concatenation_operator) diff --git a/content/wiki/20201112104934-javascript_concatenation_operator.md b/content/wiki/20201112104934-javascript_concatenation_operator.md new file mode 100644 index 0000000..d944de1 --- /dev/null +++ b/content/wiki/20201112104934-javascript_concatenation_operator.md @@ -0,0 +1,13 @@ +--- +date: 2020-11-12 +id: 6214937f-f3bb-4231-a88a-fb542b668531 +title: JavaScript Concatenation Operator +--- + +# Syntax + +The + operator concatenates strings + +``` javascript +console.log("con" + "cat" + "e" + "nate") +``` diff --git a/content/wiki/20201112105050-javascript_unary_operators.md b/content/wiki/20201112105050-javascript_unary_operators.md new file mode 100644 index 0000000..d10a78c --- /dev/null +++ b/content/wiki/20201112105050-javascript_unary_operators.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-12 +id: 4a6d69e8-c72a-40c3-b81e-31a40adabbb5 +title: JavaScript Unary Operators +--- + +# Operators + +- [JavaScript Typeof + Operator](20201112105152-javascript_typeof_operator) diff --git a/content/wiki/20201112105152-javascript_typeof_operator.md b/content/wiki/20201112105152-javascript_typeof_operator.md new file mode 100644 index 0000000..7f01939 --- /dev/null +++ b/content/wiki/20201112105152-javascript_typeof_operator.md @@ -0,0 +1,16 @@ +--- +date: 2020-11-12 +id: 9e6dcb99-ffe8-48f2-95d2-3ec5dd20dc9f +title: JavaScript Typeof Operator +--- + +# Description + +Returns value type. + +# Syntax + +``` javascript +console.log(typeof 4.5) +console.log(typeof "x") +``` diff --git a/content/wiki/20201112105310-javascript_comparison_operators.md b/content/wiki/20201112105310-javascript_comparison_operators.md new file mode 100644 index 0000000..1b49167 --- /dev/null +++ b/content/wiki/20201112105310-javascript_comparison_operators.md @@ -0,0 +1,24 @@ +--- +date: 2020-11-12 +id: 0617f7af-2e55-40b5-b83a-6157703a9cd6 +title: JavaScript Comparison Operators +--- + +# Operators + +``` javascript +console.log(4 >= 3) +console.log(4 <= 3) +console.log(4 == 3) +console.log(4 != 3) +console.log(0 == false) +console.log(0 === false) +console.log(0 != false) +console.log(0 !== false) +``` + +The only value in JavaScript that is not equal to itself is NaN + +``` javascript +console.log(NaN == NaN) +``` diff --git a/content/wiki/20201112105647-javascript_logical_operators.md b/content/wiki/20201112105647-javascript_logical_operators.md new file mode 100644 index 0000000..e0a7ce0 --- /dev/null +++ b/content/wiki/20201112105647-javascript_logical_operators.md @@ -0,0 +1,21 @@ +--- +date: 2020-11-12 +id: bf07be35-319c-4a57-8ee5-658e4591ec8c +title: JavaScript Logical Operators +--- + +# Syntax + +``` javascript +console.log(true && false) +console.log(true && true) +console.log(false || true) +console.log(false || false) +``` + +! is a unary operator that flips the value given to it + +``` javascript +console.log(true && !true) +console.log(true && !false) +``` diff --git a/content/wiki/20201112105833-javascript_short_circuiting_of_logical_operators.md b/content/wiki/20201112105833-javascript_short_circuiting_of_logical_operators.md new file mode 100644 index 0000000..069ae44 --- /dev/null +++ b/content/wiki/20201112105833-javascript_short_circuiting_of_logical_operators.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-12 +id: 2e3bb381-730b-416b-bd83-b99510244927 +title: JavaScript Short Circuiting of Logical Operators +--- + +# Syntax + +``` javascript +console.log(null || "user") +console.log("Agnes" || "user") +console.log(0 || -1) +console.log("" || "!?") +console.log(true || "X") +console.log(false || "X") +console.log(true && "X") +console.log(false && "X") +``` diff --git a/content/wiki/20201112110025-javascript_conditional_ternary_operator.md b/content/wiki/20201112110025-javascript_conditional_ternary_operator.md new file mode 100644 index 0000000..9e4bb6e --- /dev/null +++ b/content/wiki/20201112110025-javascript_conditional_ternary_operator.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-12 +id: 4a8846d3-a3c3-4edc-8fa1-a2de76f1094f +title: JavaScript Conditional (Ternary) Operator +--- + +# Syntax + +``` javascript +console.log(true ? 1 : 2) +console.log(false ? 1 : 2) +``` diff --git a/content/wiki/20201112110203-javascript_exponentation_operator.md b/content/wiki/20201112110203-javascript_exponentation_operator.md new file mode 100644 index 0000000..e4a2af6 --- /dev/null +++ b/content/wiki/20201112110203-javascript_exponentation_operator.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-12 +id: fe4897ce-ad46-4279-a35b-9e7958645f9c +title: JavaScript Exponentation Operator +--- + +# Syntax + +``` javascript +console.log(6 ** 2); // 36 +``` diff --git a/content/wiki/20201112111910-named_arguments.md b/content/wiki/20201112111910-named_arguments.md new file mode 100644 index 0000000..6ab17d4 --- /dev/null +++ b/content/wiki/20201112111910-named_arguments.md @@ -0,0 +1,26 @@ +--- +date: 2020-11-12 +id: 1fbecac8-5649-4612-9430-98d0f3ac2ca8 +title: PHP Named Arguments +--- + +# Description + +Allowes named arguments[^1] to be used to access parameters in random +order, as in [JavaScript](20200922162127-named_parameters). + +# Syntax + +``` php +function tralala(string $a, string $b, string $c) +{ + echo $a.' '.$b.' '.$c; +} + +tralala(b: 'la', c: 'la', a: 'tra'); +// tra la la +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201112113236-trailing_comma_in_parameter_lists.md b/content/wiki/20201112113236-trailing_comma_in_parameter_lists.md new file mode 100644 index 0000000..40ad0f7 --- /dev/null +++ b/content/wiki/20201112113236-trailing_comma_in_parameter_lists.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-12 +id: 4bf0a31f-50eb-4b42-8d5d-54e6777147a4 +title: Trailing Comma in Parameter Lists +--- + +# Description + +PHP8 allows trailing commas[^1] to bue used in parameters lists. + +# Syntax + +``` php +function tralala(string $a, string $b, string $c,) {} +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201112120118-symfony_4_3.md b/content/wiki/20201112120118-symfony_4_3.md new file mode 100644 index 0000000..c3efeab --- /dev/null +++ b/content/wiki/20201112120118-symfony_4_3.md @@ -0,0 +1,96 @@ +--- +date: 2020-11-12 +id: 12ab3998-b4f3-4754-ab3c-a5d3ebe3c8ce +title: Symfony 4.3 +--- + +# What's new + +## Components + +### Console + +- [Console Hyperlinks](20201112120358-symfony_console_hyperlinks) +- [iterate() method](20201112130435-iterate_method) + +### Mailer + +- [Mailer Component](20201112135249-mailer_component) + +### Mime + +- [Mime Component](20201112140650-mime_component) + +## Configuration + +- [Automatic Search Engine + Protection](20201112124832-automatic_search_engine_protection) + +## Routing + +- [Always Include Route Default + Values](20201112121416-always_include_route_default_values) +- [UTF8 Routing Option](20201112132747-utf8_routing_option) + +## Constraints + +### Bic constraint + +- [Validate BIC and IBAN Codes + Together](20201112123244-validate_bic_and_iban_codes_together) + +### CardScheme constraint + +- [CardScheme Constraint](20201112123704-cardscheme_constraint) + +### Compromised password constraint + +- [Compromised Password + Constraint](20201112134752-compromised_password_constraint) + +### HttpClient Component + +- [HttpClient Component](20201112140448-httpclient_component) + +### JSON constraint + +- [JSON Constraint](20201112125637-symfony_json_constraint) + +### NotBlank constraint + +- [NotBlank allowNull](20201112130816-notblank_allownull) + +### Unique constraint + +- [Unique Constraint](20201112132331-unique_constraint) + +### Timeone constraint + +- [Timezone Constraint](20201112134545-timezone_constraint) + +### Number constraints + +- [Number Constraints](20201112140917-number_constraints) + +## Services + +- [Deprecating Service + Aliases](20201112124159-deprecating_service_aliases) +- [Configuring Services With Immutable + Setters](20201112131310-configuring_services_with_immutable_setters) + +## Sessions + +- [Configurable Session ID](20201112125413-configurable_session_id) + +## Validation + +- [Automatic Validation Based on Doctrine + Mapping](20201112132007-automatic_validation_based_on_doctrine_mapping) + +## Password hashers + +- Deprecated [Argon2i Password + Hasher](20201110152730-symfony_argon2i_password_hasher) +- [Sodium password encoder](20201112133736-sodium_password_encoder) +- [Symfony Native Encoder](20201112135851-symfony_native_encoder) diff --git a/content/wiki/20201112120358-symfony_console_hyperlinks.md b/content/wiki/20201112120358-symfony_console_hyperlinks.md new file mode 100644 index 0000000..2efcc15 --- /dev/null +++ b/content/wiki/20201112120358-symfony_console_hyperlinks.md @@ -0,0 +1,13 @@ +--- +date: 2020-11-12 +id: 9ce2a2cc-a3d4-4440-8dce-0765ebbd006a +title: Symfony Console Hyperlinks +--- + +# Syntax + +``` php +// hyperlink syntax: THE_LINK_TEXT +$output->writeln('Symfony Homepage'); +$output->writeln('View Issue'); +``` diff --git a/content/wiki/20201112121020-symfony_il8n.md b/content/wiki/20201112121020-symfony_il8n.md new file mode 100644 index 0000000..a03bea2 --- /dev/null +++ b/content/wiki/20201112121020-symfony_il8n.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-12 +id: 92714879-c1f4-4570-952b-c7ab12908aca +title: Symfony Il8n +--- + +- [Internationalized + Routing](20201110154548-internationalized_routing) +- [Pseudo-localization + Translator](20201117100112-pseudo_localization_translator) diff --git a/content/wiki/20201112121416-always_include_route_default_values.md b/content/wiki/20201112121416-always_include_route_default_values.md new file mode 100644 index 0000000..4fbae14 --- /dev/null +++ b/content/wiki/20201112121416-always_include_route_default_values.md @@ -0,0 +1,38 @@ +--- +date: 2020-11-12 +id: 63017411-62dd-4586-86c5-4b0edc70114d +title: Always Include Route Default Values +--- + +# Description + +Sometimes when generating URLs you have situations where you don't want +the default value in the URL. + +# Syntax + +``` php +/** + * @Route("/blog/{!page}", name="blog_list") + */ +public function list($page = 1) +{ + // ... +} +``` + +``` php +$url = $router->generate('blog_list'); // $url = '/blog/1' +$url = $router->generate('blog_list', ['page' => 1]); // $url = '/blog/1' +$url = $router->generate('blog_list', ['page' => 7]); // $url = '/blog/7' +``` + +``` php +/** + * @Route("/blog/{page}.{!_format?html}", name="blog_list") + */ +public function list($page = 1) +{ + // ... +} +``` diff --git a/content/wiki/20201112121938-symfony_constraints.md b/content/wiki/20201112121938-symfony_constraints.md new file mode 100644 index 0000000..471e088 --- /dev/null +++ b/content/wiki/20201112121938-symfony_constraints.md @@ -0,0 +1,52 @@ +--- +date: 2020-11-12 +id: d69cb1c0-fc5d-406e-beab-e82ee12dc603 +title: Symfony Constraints +--- + +# Attributes + +As of [Symfony 5.2](20201117095953-symfony_5_2), validation constraints +can be defined as +[attributes](20201117112727-define_constraints_as_attributes). + +# Constraints + +- [Compromised Password + Constraint](20201112134752-compromised_password_constraint) +- [Hostname Constraint](20201116132411-hostname_constraint) +- [JSON Constraint](20201112125637-symfony_json_constraint) +- [NotBlank Constraint](20201112130710-notblank_constraint) +- [Timezone Constraint](20201112134545-timezone_constraint) +- [Type Constraint](20201113172517-type_constraint) +- [Unique Constraint](20201112132331-unique_constraint) +- [ULID Constraint](20201117104332-ulid_constraint) + +## Compound constraints + +- [AtLeastOneOf Constraint](20201116134435-atleastoneof_constraint) +- [Compound Constraint](20201116124210-compound_constraint) +- [Sequentially Constraint](20201116124823-sequentially_constraint) + +## Expressions + +- [ExpressionLanguage + Constraint](20201109150640-expressionlanguage_constraint) +- [ExpressionLanguageSyntax + Constraint](20201116135523-expressionlanguagesyntax_constraint) + +## Number constraints + +- [DivisibleBy + Constraint](20201111103048-symfony_divisibleby_constraint) +- [Number Constraints](20201112140917-number_constraints) + +## Valid constraints + +- [Groups support for Valid + constraint](20201109145724-groups_support_for_valid_constraint) + +## Financial constraints + +- [Bic Constraint](20201112122929-bic_constraint) +- [CardScheme Constraint](20201112123704-cardscheme_constraint) diff --git a/content/wiki/20201112122929-bic_constraint.md b/content/wiki/20201112122929-bic_constraint.md new file mode 100644 index 0000000..ce74c84 --- /dev/null +++ b/content/wiki/20201112122929-bic_constraint.md @@ -0,0 +1,20 @@ +--- +date: 2020-11-12 +id: 5efb845b-d2ae-4614-be1e-bbd6d5fca74e +title: Bic Constraint +--- + +# Description + +Validates BIC[^1]. Also See ISO-9362[^2] + +# Changes + +- [Validate BIC and IBAN Codes + Together](20201112123244-validate_bic_and_iban_codes_together) + +# Footnotes + +[^1]: + +[^2]: diff --git a/content/wiki/20201112123244-validate_bic_and_iban_codes_together.md b/content/wiki/20201112123244-validate_bic_and_iban_codes_together.md new file mode 100644 index 0000000..acdf1fc --- /dev/null +++ b/content/wiki/20201112123244-validate_bic_and_iban_codes_together.md @@ -0,0 +1,39 @@ +--- +date: 2020-11-12 +id: 65f016de-b501-447f-bf81-6bf4f196330f +title: Validate BIC and IBAN Codes Together +--- + +# Syntax + +``` php +use Symfony\Component\Validator\Constraints as Assert; +// ... + +public static function loadValidatorMetadata(ClassMetadata $metadata) +{ + $metadata->addPropertyConstraint('businessIdentifierCode', new Assert\Bic([ + 'iban' => 'FR1420041010050500013M02606', + ])); +} +``` + +``` php +use Symfony\Component\Validator\Constraints as Assert; +// ... + +class Transaction +{ + /** + * @Assert\Bic(ibanPropertyPath = "accountNumber") + */ + protected $businessIdentifierCode; + + /** + * @Assert\Iban + */ + protected $accountNumber; + + // public getters for properties ... +} +``` diff --git a/content/wiki/20201112123704-cardscheme_constraint.md b/content/wiki/20201112123704-cardscheme_constraint.md new file mode 100644 index 0000000..fbfa74c --- /dev/null +++ b/content/wiki/20201112123704-cardscheme_constraint.md @@ -0,0 +1,28 @@ +--- +date: 2020-11-12 +id: c74d4f32-ff6b-419e-8ed7-eb0b018de44d +title: CardScheme Constraint +--- + +See Universal Air Travel Plan[^1] for more details. + +# Syntax + +``` php +// ... + +class Transaction +{ + /** + * @Assert\CardScheme( + * schemes={"AMEX", "MASTERCARD", "UATP", "VISA"}, + * message="Your credit card number is invalid." + * ) + */ + protected $cardNumber; +} +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201112124159-deprecating_service_aliases.md b/content/wiki/20201112124159-deprecating_service_aliases.md new file mode 100644 index 0000000..be748b1 --- /dev/null +++ b/content/wiki/20201112124159-deprecating_service_aliases.md @@ -0,0 +1,34 @@ +--- +date: 2020-11-12 +id: 340acfc8-c621-4578-a588-c306ebaa4d75 +title: Deprecating Service Aliases +--- + +# Description + +It's possible to deprecate [service](20201112124304-symfony_services) +aliases + +# Syntax + +``` yaml +# config/services.yaml +services: + # ... + + app.mailer: + alias: App\Mail\PhpMailer + deprecated: ~ +``` + +## Custom error message + +``` yaml +# config/services.yaml +services: + # ... + + app.mailer: + alias: App\Mail\PhpMailer + deprecated: 'The "%alias_id%" service alias is deprecated.' +``` diff --git a/content/wiki/20201112124304-symfony_services.md b/content/wiki/20201112124304-symfony_services.md new file mode 100644 index 0000000..51475d7 --- /dev/null +++ b/content/wiki/20201112124304-symfony_services.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-12 +id: be8665e2-83e3-408f-b532-5c7e1fdc4729 +title: Symfony Services +--- + +# Decoration + +- [Service Decoration](20201116132826-service_decoration) +- [Stack Decorators](20201116133113-stack_decorators) + +# Deprecation + +- [Deprecate Public Services Into Private + Services](20201116134758-deprecate_public_services_into_private_services) +- [Deprecating Service + Aliases](20201112124159-deprecating_service_aliases) + +# Setters + +- [Configuring Services With Immutable + Setters](20201112131310-configuring_services_with_immutable_setters) diff --git a/content/wiki/20201112124715-symfony_configuration.md b/content/wiki/20201112124715-symfony_configuration.md new file mode 100644 index 0000000..5bb2f5a --- /dev/null +++ b/content/wiki/20201112124715-symfony_configuration.md @@ -0,0 +1,45 @@ +--- +date: 2020-11-12 +id: 3bdd7ddf-9039-438a-abc7-435d6ccc1a61 +title: Symfony Configuration +--- + +- [Automatic Search Engine + Protection](20201112124832-automatic_search_engine_protection) +- [Configurable Session ID](20201112125413-configurable_session_id) +- [Configuring Services With Immutable + Setters](20201112131310-configuring_services_with_immutable_setters) + +# Controller + +- [Front Controller + Configuration](20201117114443-front_controller_configuration) + +# Password hashers + +- [Sodium password encoder](20201112133736-sodium_password_encoder) +- [Symfony Native Encoder](20201112135851-symfony_native_encoder) + (best practice since [Symfony 4.3](20201112120118-symfony_4_3)) + +# Encryption + +- [Ecrypted Secrets + Management](20201113174444-ecrypted_secrets_management) + +# Events + +[Event Listeners](20201113175527-event_listeners) + +# Firewalls + +- [Lazy Firewalls](20201113183038-lazy_firewalls) + +# Translator + +- [Pseudo-localization + Translator](20201117100112-pseudo_localization_translator) + +# RateLimiter Component + +- [Symfony RateLimiter + Component](20201117113404-symfony_ratelimiter_component) diff --git a/content/wiki/20201112124832-automatic_search_engine_protection.md b/content/wiki/20201112124832-automatic_search_engine_protection.md new file mode 100644 index 0000000..dccefe3 --- /dev/null +++ b/content/wiki/20201112124832-automatic_search_engine_protection.md @@ -0,0 +1,20 @@ +--- +date: 2020-11-12 +id: c6744b2e-f845-4ac7-83d5-ef206743e4a6 +title: Automatic Search Engine Protection +--- + +# Description + +Symfony dissalows search engine indexing for development applications. A +`X-Robots-Tag: noindex` HTTP header is added to all responses. This can +be manually overridden in the config. + +# Syntax + +``` yaml +# config/packages/framework.yaml +framework: + # ... + disallow_search_engine_index: false +``` diff --git a/content/wiki/20201112125413-configurable_session_id.md b/content/wiki/20201112125413-configurable_session_id.md new file mode 100644 index 0000000..30975eb --- /dev/null +++ b/content/wiki/20201112125413-configurable_session_id.md @@ -0,0 +1,20 @@ +--- +date: 2020-11-12 +id: 9a6ba6b5-92b8-4422-a31a-3d78ba563ef2 +title: Configurable Session ID +--- + +# Syntax + +``` yaml +# config/packages/framework.yaml +framework: + session: + # configures the length of the string used for the session ID + # integer; default = 32; valid values = from 22 to 256 (both inclusive) + sid_length: 64 + + # configures the number of bits in encoded session ID character + # integer; default = 4; valid values: 4, 5, or 6. + sid_bits_per_character: 4 +``` diff --git a/content/wiki/20201112125637-symfony_json_constraint.md b/content/wiki/20201112125637-symfony_json_constraint.md new file mode 100644 index 0000000..78b849c --- /dev/null +++ b/content/wiki/20201112125637-symfony_json_constraint.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-12 +id: 4e20e5e5-06b6-4280-9cd0-7b08585a762b +title: Symfony JSON Constraint +--- + +# Syntax + +``` php +// src/Entity/Book.php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class Book +{ + /** + * @Assert\Json(message = "This is not valid JSON") + */ + protected $chapters; +} +``` diff --git a/content/wiki/20201112125813-symfony_json.md b/content/wiki/20201112125813-symfony_json.md new file mode 100644 index 0000000..2f826cb --- /dev/null +++ b/content/wiki/20201112125813-symfony_json.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-12 +id: 675c8bfd-a684-441b-84db-76ba6ccc4e77 +title: Symfony JSON +--- + +# Constraints + +- [JSON Constraint](20201112125637-symfony_json_constraint) diff --git a/content/wiki/20201112130234-symfony_console_iterable_progress_bars.md b/content/wiki/20201112130234-symfony_console_iterable_progress_bars.md new file mode 100644 index 0000000..76b6c6b --- /dev/null +++ b/content/wiki/20201112130234-symfony_console_iterable_progress_bars.md @@ -0,0 +1,24 @@ +--- +date: 2020-11-12 +id: b4fc3714-24f9-4eb6-9d46-3c42bdcd5be2 +title: Symfony Console Iterable Progress Bars +--- + +# Changes + +- [iterate() method](20201112130435-iterate_method) + +# Syntax + +``` php +use Symfony\Component\Console\Helper\ProgressBar; + +$progressBar = new ProgressBar($output); +$progressBar->start(); + +// ... do some work +$progressBar->advance(); + +// needed to ensure that the bar reaches 100% +$progressBar->finish(); +``` diff --git a/content/wiki/20201112130435-iterate_method.md b/content/wiki/20201112130435-iterate_method.md new file mode 100644 index 0000000..2787288 --- /dev/null +++ b/content/wiki/20201112130435-iterate_method.md @@ -0,0 +1,33 @@ +--- +date: 2020-11-12 +id: f5983e81-f975-4913-b6c5-5211493841b7 +title: iterate() method +--- + +# Syntax + +``` php +$iterable = function () { + yield 1; + yield 2; + // ... +}; +``` + +``` php +use Symfony\Component\Console\Helper\ProgressBar; + +$progressBar = new ProgressBar($output); + +foreach ($progressBar->iterate($iterable) as $value) { + // ... do some work +} +``` + +## Non countable variable + +``` php +foreach ($progressBar->iterate($iterable, 100) as $value) { + // ... do some work +} +``` diff --git a/content/wiki/20201112130710-notblank_constraint.md b/content/wiki/20201112130710-notblank_constraint.md new file mode 100644 index 0000000..c8f032c --- /dev/null +++ b/content/wiki/20201112130710-notblank_constraint.md @@ -0,0 +1,25 @@ +--- +date: 2020-11-12 +id: ba104198-9038-4219-994e-503ee655d9f3 +title: NotBlank Constraint +--- + +# Syntax + +``` php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class SomeEntity +{ + /** + * @Assert\NotBlank() + */ + protected $someProperty; +} +``` + +## allowNull + +[NotBlank allowNull](20201112130816-notblank_allownull) diff --git a/content/wiki/20201112130816-notblank_allownull.md b/content/wiki/20201112130816-notblank_allownull.md new file mode 100644 index 0000000..01b6d8c --- /dev/null +++ b/content/wiki/20201112130816-notblank_allownull.md @@ -0,0 +1,27 @@ +--- +date: 2020-11-12 +id: 47dd501e-a567-481a-8d85-5eb1cd0bad15 +title: NotBlank allowNull +--- + +# Description + +The default option is `false`. If set to true then `null` values will be +considered valid. + +# Syntax + +``` php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class SomeEntity +{ + /** + * @Assert\NotBlank(allowNull = true) + */ + protected $someProperty; +} + +``` diff --git a/content/wiki/20201112131310-configuring_services_with_immutable_setters.md b/content/wiki/20201112131310-configuring_services_with_immutable_setters.md new file mode 100644 index 0000000..30745ef --- /dev/null +++ b/content/wiki/20201112131310-configuring_services_with_immutable_setters.md @@ -0,0 +1,72 @@ +--- +date: 2020-11-12 +id: 51f4dd9e-6f11-485d-8544-f302e71fc036 +title: Configuring Services With Immutable Setters +--- + +# Description + +A common need in some Symfony applications is to use immutable services +while still using traits for composing their optional features. Although +the Symfony service container supports setter injection, they have some +drawbacks (e.g. setters can be called more than just at the time of +construction so you cannot be sure the dependency is not replaced during +the lifetime of the object). + +A pattern to solve this problem are "wither methods". These methods +typically use the with word as the prefix of their names (e.g. +withPropertyName()) and they return a copy of an instance of an +immutable class with only that one property changed: + +``` php +class MyService +{ + use LoggerAwareTrait; + + // ... +} + +trait LoggerAwareTrait +{ + private $logger; + + public function withLogger(LoggerInterface $logger) + { + $new = clone $this; + $new->logger = $logger; + + return $new; + } +} + +$service = new MyService(); +$service = $service->withLogger($logger); +``` + +# Syntax + +``` yaml +# config/services.yaml +services: + MyService: + # ... + calls: + # the TRUE argument turns this into a wither method + - ['withLogger', ['@logger'], true] +``` + +``` php +class MyService +{ + // ... + + /** + * @required + * @return static + */ + public function withLogger(LoggerInterface $logger) + { + // ... + } +} +``` diff --git a/content/wiki/20201112131845-doctrine.md b/content/wiki/20201112131845-doctrine.md new file mode 100644 index 0000000..b037717 --- /dev/null +++ b/content/wiki/20201112131845-doctrine.md @@ -0,0 +1,21 @@ +--- +date: 2020-11-12 +id: 78611b42-959f-4a7a-b1d9-97f20bf73ea0 +title: Doctrine +--- + +# Symfony + +## Validation + +- [Automatic Validation Based on Doctrine + Mapping](20201112132007-automatic_validation_based_on_doctrine_mapping) + +## Listeners + +- [Doctrine Entity + Listeners](20201113180551-doctrine_entity_listeners) + +## Types + +- [UUID / ULID Types](20201117101452-uuid_ulid_types) diff --git a/content/wiki/20201112132007-automatic_validation_based_on_doctrine_mapping.md b/content/wiki/20201112132007-automatic_validation_based_on_doctrine_mapping.md new file mode 100644 index 0000000..037fd90 --- /dev/null +++ b/content/wiki/20201112132007-automatic_validation_based_on_doctrine_mapping.md @@ -0,0 +1,40 @@ +--- +date: 2020-11-12 +id: c7132269-2084-4d87-9888-0f860db29aaf +title: Automatic Validation Based on Doctrine Mapping +--- + +# Description + +From [Symfony 4.3](20201112120118-symfony_4_3), Symfony introduces +automatic validation based on Doctrine mapping. + +# Examples + +``` php +use Doctrine\ORM\Mapping as ORM; + +/** @ORM\Entity */ +class SomeEntity +{ + // ... + + /** @ORM\Column(length=4) */ + public $pinCode; +} +``` + +``` php +$entity = new SomeEntity(); +$entity->pinCode = '1234567890'; +$violationList = $validator->validate($entity); +``` + +``` php +$violationList = $validator->validate($entity); + +var_dump((string) $violationList); +// Object(App\Entity\SomeEntity).columnLength:\n +// This value is too long. It should have 4 characters or less. +// (code d94b19cc-114f-4f44-9cc4-4138e80a87b9)\n +``` diff --git a/content/wiki/20201112132331-unique_constraint.md b/content/wiki/20201112132331-unique_constraint.md new file mode 100644 index 0000000..cbaf63c --- /dev/null +++ b/content/wiki/20201112132331-unique_constraint.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-12 +id: ebceb7b8-5242-482b-b258-2cf9c25d1788 +title: Unique Constraint +--- + +# Syntax + +``` php +// src/Entity/Person.php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class Person +{ + /** + * @Assert\Unique(message="The {{ value }} email is repeated.") + */ + protected $contactEmails; +} +``` diff --git a/content/wiki/20201112132747-utf8_routing_option.md b/content/wiki/20201112132747-utf8_routing_option.md new file mode 100644 index 0000000..530b48b --- /dev/null +++ b/content/wiki/20201112132747-utf8_routing_option.md @@ -0,0 +1,23 @@ +--- +date: 2020-11-12 +id: 45b1f81a-d5f4-4f28-99d6-6a1592c75f7d +title: UTF8 Routing Option +--- + +# Syntax + +``` php +// PHP Annotations + +/** + * @Route("/category/{name}", name="category", utf8=true) + */ +public function category() +``` + +``` yaml +category: + path: /category/{name} + controller: App\Controller\DefaultController::category + utf8: true +``` diff --git a/content/wiki/20201112132858-symfony_utf_8_support.md b/content/wiki/20201112132858-symfony_utf_8_support.md new file mode 100644 index 0000000..ba6280b --- /dev/null +++ b/content/wiki/20201112132858-symfony_utf_8_support.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-12 +id: 72aaa2a1-89f1-4f86-b666-299d77e5a75f +title: Symfony UTF-8 Support +--- + +- [UTF8 Routing Option](20201112132747-utf8_routing_option) diff --git a/content/wiki/20201112133603-symfony_passwords.md b/content/wiki/20201112133603-symfony_passwords.md new file mode 100644 index 0000000..825899c --- /dev/null +++ b/content/wiki/20201112133603-symfony_passwords.md @@ -0,0 +1,14 @@ +--- +date: 2020-11-12 +id: d7cf5110-7cf3-4228-bf6a-552e20a6ffd6 +title: Symfony Passwords +--- + +# Hashers + +- [Argon2i Password + Hasher](20201110152730-symfony_argon2i_password_hasher) + Deprecated in [Symfony 4.3](20201112120118-symfony_4_3) +- [Sodium password encoder](20201112133736-sodium_password_encoder) +- [Native Encoder](20201112135851-symfony_native_encoder) (best + practice) diff --git a/content/wiki/20201112133736-sodium_password_encoder.md b/content/wiki/20201112133736-sodium_password_encoder.md new file mode 100644 index 0000000..673ac96 --- /dev/null +++ b/content/wiki/20201112133736-sodium_password_encoder.md @@ -0,0 +1,24 @@ +--- +date: 2020-11-12 +id: ebc9cf71-62ed-44fa-98c6-b2d01fbd69fe +title: Sodium password encoder +--- + +# Description + +In Symfony 4.3, the [Symfony Argon2i Password +Hasher](20201110152730-symfony_argon2i_password_hasher) is deprecated. +`SodiumPasswordEncoder` is used instead. Best practice since [Symfony +4.3](20201112120118-symfony_4_3) is to use the [native +encoder](20201112135851-symfony_native_encoder). + +# Syntax + +``` yaml +# config/packages/security.yml +security: + # ... + encoders: + App\Entity\User: + algorithm: sodium +``` diff --git a/content/wiki/20201112134545-timezone_constraint.md b/content/wiki/20201112134545-timezone_constraint.md new file mode 100644 index 0000000..29f8c88 --- /dev/null +++ b/content/wiki/20201112134545-timezone_constraint.md @@ -0,0 +1,34 @@ +--- +date: 2020-11-12 +id: ba952b1d-0609-4bc6-94b9-0192df3bf4f2 +title: Timezone Constraint +--- + +# Syntax + +``` php +// src/Entity/UserSettings.php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class UserSettings +{ + /** + * @Assert\Timezone + */ + protected $timezone; +} +``` + +``` php +// Consider valid only the timezones from countries in America continent + +/** @Assert\Timezone(zone=\DateTimeZone::AMERICA) */ +protected $timezone; + +// Consider valid only the Chinese timezones + +/** @Assert\Timezone(zone=\DateTimeZone::PER_COUNTRY, countryCode="CN") */ +protected $timezone; +``` diff --git a/content/wiki/20201112134545-timezozne_constraint.md b/content/wiki/20201112134545-timezozne_constraint.md new file mode 100644 index 0000000..5c7bc8c --- /dev/null +++ b/content/wiki/20201112134545-timezozne_constraint.md @@ -0,0 +1,40 @@ +--- +date: 2020-11-12 +id: f028709b-5851-4a8e-8c3c-097ebbe27c39 +title: Timezozne Constraint +--- + +# Syntax + +``` php +// src/Entity/UserSettings.php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class UserSettings +{ + /** + * @Assert\Timezone + */ + protected $timezone; +} +``` + +``` php +// Consider valid only the timezones from countries in America continent + +/** @Assert\Timezone(zone=\DateTimeZone::AMERICA) */ +protected $timezone; + +// Consider valid only the Chinese timezones + +/** @Assert\Timezone(zone=\DateTimeZone::PER_COUNTRY, countryCode="CN") */ +protected $timezone; +``` + +# Related + +- [Symfony Constraints](20201112121938-symfony_constraints) +- [Symfony Annotations](20201109142218-symfony_annotations) +- [Symfony 4.3](20201112120118-symfony_4_3) diff --git a/content/wiki/20201112134752-compromised_password_constraint.md b/content/wiki/20201112134752-compromised_password_constraint.md new file mode 100644 index 0000000..df3aae0 --- /dev/null +++ b/content/wiki/20201112134752-compromised_password_constraint.md @@ -0,0 +1,31 @@ +--- +date: 2020-11-12 +id: 1b282a21-2736-404a-a788-5a362fcba479 +title: Compromised Password Constraint +--- + +# Description + +Internally, the constraint makes an HTTP request to the API provided by +the haveibeenpwned.com website. In the request, the validator doesn't +send the raw password but only the few first characters of the result of +encoding it using SHA-1. + +# Syntax + +``` php +// src/Entity/User.php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class User +{ + // ... + + /** + * @Assert\NotCompromisedPassword + */ + protected $rawPassword; +} +``` diff --git a/content/wiki/20201112135249-mailer_component.md b/content/wiki/20201112135249-mailer_component.md new file mode 100644 index 0000000..5a6bc9a --- /dev/null +++ b/content/wiki/20201112135249-mailer_component.md @@ -0,0 +1,74 @@ +--- +date: 2020-11-12 +id: c6a317d3-cdda-4c9b-bf03-5e36bce8bc57 +title: Mailer Component +--- + +# Description + +Added in [Symfony 4.3](20201112120118-symfony_4_3). Out of the box the +following services are supported: + +- Amazon SES +- MailChimp +- Mailgun +- Gmail +- Postmark +- SendGrid + +Services need to be installed seperately: + +``` shell +composer require symfony/amazon-mailer +``` + +And environment variables need to be configured: + +``` shell +AWS_ACCESS_KEY=... +AWS_SECRET_KEY=... +MAILER_DSN=smtp://$AWS_ACCESS_KEY:$AWS_SECRET_KEY@ses +``` + +# Syntax + +``` php +use Symfony\Component\Mailer\MailerInterface; +use Symfony\Component\Mime\Email; + +class SomeService +{ + private $mailer; + + public function __construct(MailerInterface $mailer) + { + $this->mailer = $mailer; + } + + public function sendNotification() + { + $email = (new Email()) + ->from('hello@example.com') + ->to('you@example.com') + ->subject('Time for Symfony Mailer!') + ->text('Sending emails is fun again!') + ->html('

See Twig integration for better HTML integration!

'); + + $this->mailer->send($email); + } +} +``` + +# Signing Messages + +It's also possible to [sign and +encrypt](20201113173159-signing_and_encrypting_messages) messages. + +# DKIM email authentication + +- DKIM[^1] authentication is + [supported](20201117104659-dkim_email_authentication) as well. + +# Footnotes + +[^1]: diff --git a/content/wiki/20201112135851-symfony_native_encoder.md b/content/wiki/20201112135851-symfony_native_encoder.md new file mode 100644 index 0000000..9677cee --- /dev/null +++ b/content/wiki/20201112135851-symfony_native_encoder.md @@ -0,0 +1,40 @@ +--- +date: 2020-11-12 +id: cd2d3da1-7251-49f1-939b-460c92ba317b +title: Symfony Native Encoder +--- + +# Description + +This is best practice since [Symfony 4.3](20201112120118-symfony_4_3). + +This value auto-selects the best possible hashing algorithm, so it +doesn't refer to an specific algorithm and it will change in the future. +The current implementation uses `'sodium'` if possible and otherwise, it +falls back to `'native'`. + +The `'native'` config option is associated with the +`NativePasswordEncoder` class, which is the other main change about +password hashers in Symfony 4.3. This new encoder relies both on Symfony +and PHP to select the best possible algorithm. + +The current `NativePasswordEncoder` implementation tries to use any of +the Argon2 variants (Argon2i or Argon2id) before falling back to Bcrypt. +However, if the `PASSWORD_DEFAULT` PHP constant changes in the future, +that new algorithm will be selected (if PHP defines it as stronger than +Argon2). + +# Syntax + +``` yaml +# config/packages/security.yml +security: + # ... + encoders: + App\Entity\User: + algorithm: auto +``` + +# Changes + +- [Password Migrations](20201113181759-password_migrations) diff --git a/content/wiki/20201112140448-httpclient_component.md b/content/wiki/20201112140448-httpclient_component.md new file mode 100644 index 0000000..45e74d9 --- /dev/null +++ b/content/wiki/20201112140448-httpclient_component.md @@ -0,0 +1,41 @@ +--- +date: 2020-11-12 +id: c8b16c01-3921-4121-bb03-82f0b497eb31 +title: HttpClient Component +--- + +# Syntax + +``` php +use Symfony\Component\HttpClient\HttpClient; + +$httpClient = HttpClient::create(); +$response = $httpClient->request('GET', 'https://api.github.com/repos/symfony/symfony-docs'); +``` + +``` php +$statusCode = $response->getStatusCode(); +// $statusCode = 200 +$content = $response->getContent(); +// returns the raw content returned by the server (JSON in this case) +// $content = '{"id":521583, "name":"symfony-docs", ...}' +$content = $response->toArray(); +// transforms the response JSON content into a PHP array +// $content = ['id' => 521583, 'name' => 'symfony-docs', ...] +``` + +``` php +// the response of this request will be a 403 HTTP error +$response = $httpClient->request('GET', 'https://httpbin.org/status/403'); + +// this code results in a Symfony\Component\HttpClient\Exception\ClientException +// because it doesn't check the status code of the response +$content = $response->getContent(); + +// do this instead +if (200 !== $response->getStatusCode()) { + // handle the HTTP request error (e.g. retry the request) +} else { + $content = $response->getContent(); +} +``` diff --git a/content/wiki/20201112140650-mime_component.md b/content/wiki/20201112140650-mime_component.md new file mode 100644 index 0000000..dee9799 --- /dev/null +++ b/content/wiki/20201112140650-mime_component.md @@ -0,0 +1,63 @@ +--- +date: 2020-11-12 +id: 5649f9c4-6f96-46c2-b3a2-45c6a28904c1 +title: Mime Component +--- + +# Syntax + +``` php +use Symfony\Component\Mime\Email; + +$email = (new Email()) + ->from('fabien@symfony.com') + ->to('foo@example.com') + ->subject('Important Notification') + ->text('Lorem ipsum...') + ->html('

Lorem ipsum

...

') +; +``` + +``` php +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\Part\Multipart\AlternativePart; +use Symfony\Component\Mime\Part\TextPart; + +$headers = (new Headers()) + ->addMailboxListHeader('From', ['fabien@symfony.com']) + ->addMailboxListHeader('To', ['foo@example.com']) + ->addTextHeader('Subject', 'Important Notification') +; + +$textContent = new TextPart('Lorem ipsum...'); +$htmlContent = new TextPart('

Lorem ipsum

...

', 'html'); +$body = new AlternativePart($textContent, $htmlContent); + +$email = new Message($headers, $body); +``` + +## Twig integeration + +``` php +use Symfony\Bridge\Twig\Mime\TemplatedEmail; + +$email = (new TemplatedEmail()) + ->from('fabien@symfony.com') + ->to('foo@example.com') + // ... + + // this method defines the path of the Twig template to render + ->htmlTemplate('messages/user/signup.html.twig') + + // this method defines the parameters (name => value) passed to templates + ->context([ + 'expiration_date' => new \DateTime('+7 days'), + 'username' => 'foo', + ]) +; +``` + +# Changelog + +- [Notification Emails](20201113174016-notification_emails) diff --git a/content/wiki/20201112140917-number_constraints.md b/content/wiki/20201112140917-number_constraints.md new file mode 100644 index 0000000..eece730 --- /dev/null +++ b/content/wiki/20201112140917-number_constraints.md @@ -0,0 +1,43 @@ +--- +date: 2020-11-12 +id: adc652c4-6f67-46e9-a975-8e72b852234c +title: Number Constraints +--- + +# Syntax + +``` php +use Symfony\Component\Validator\Constraints as Assert; + +class Person +{ + /** @Assert\PositiveOrZero */ + protected $siblings; + + // ... +} + +class Employee +{ + /** @Assert\Positive */ + protected $income; + + // ... +} + +class UnderGroundGarage +{ + /** @Assert\NegativeOrZero */ + protected $level; + + // ... +} + +class TransferItem +{ + /** @Assert\Negative */ + protected $withdraw; + + // ... +} +``` diff --git a/content/wiki/20201113090050-javascript_object_operators.md b/content/wiki/20201113090050-javascript_object_operators.md new file mode 100644 index 0000000..cd9e62d --- /dev/null +++ b/content/wiki/20201113090050-javascript_object_operators.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-13 +id: 8fa4c9b2-3c98-4706-ab59-6ac3b3238d81 +title: JavaScript Object Operators +--- + +# Operators + +- [In Operator](20201113090337-javascript_in_operator) +- [Instanceof Operator](20201113094246-javascript_instanceof_operator) +- [Delete Operator](20201113094652-javascript_delete_operator) diff --git a/content/wiki/20201113090337-javascript_in_operator.md b/content/wiki/20201113090337-javascript_in_operator.md new file mode 100644 index 0000000..81b07ff --- /dev/null +++ b/content/wiki/20201113090337-javascript_in_operator.md @@ -0,0 +1,37 @@ +--- +date: 2020-11-13 +id: 4cd0d42b-3414-4402-95f1-7498fbc52c20 +title: JavaScript In Operator +--- + +# Description + +`in`[^1] tells us if indices inside an [array](20200826201029-arrays) or +[object](20200826201605-objects) have no associated element. + +# Syntax + +``` javascript +const arr = ['a',,'b'] +console.log(0 in arr) // true +console.log(1 in arr) // false +console.log(2 in arr) // true +console.log(arr[1]) // undefined +``` + +``` javascript +const car = { make: "Honda", model: "Accord", year: 1998 }; + +console.log("make" in car); // true + +delete car.make; +if ("make" in car === false) { + car.make = "Suzuki"; +} + +console.log(car.make); //Suzuki +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113091110-javascript_object_properties.md b/content/wiki/20201113091110-javascript_object_properties.md new file mode 100644 index 0000000..1a21d5b --- /dev/null +++ b/content/wiki/20201113091110-javascript_object_properties.md @@ -0,0 +1,49 @@ +--- +date: 2020-11-13 +id: 3d5c7ec9-30af-4931-b6ab-2caa687f5951 +title: JavaScript Object Properties +--- + +# Description + +Values of the type [object](20200826201605-objects) are arbitrary +collections of properties + +# Syntax + +``` javascript +let tralala = { + distro: "Arch", + useWindows: false, + aListOfRandomThings: ["spoon", "fork", "modem", "keychain"], +}; + +console.log(tralala.distro); +console.log(tralala.useWindows); +console.log(tralala.aListOfRandomThings); +``` + +# Invalid binding names + +Properties with invalid binding names or numbers must be quoted: + +``` javascript +let weirdObject = { + tralala: "Chipmunk", + "this is a long binding name with spaces": "Fill in some nonsensse here" +} + +console.log(weirdObject) +``` + +# Non existant property + +Reading a non existant property returns `undefined` + +``` javascript +let Object = { + thisExists: true, +}; + +console.log(Object.undefinedProperty); // undefined +``` diff --git a/content/wiki/20201113091424-javascript_prototypes.md b/content/wiki/20201113091424-javascript_prototypes.md new file mode 100644 index 0000000..258f10b --- /dev/null +++ b/content/wiki/20201113091424-javascript_prototypes.md @@ -0,0 +1,38 @@ +--- +date: 2020-11-13 +id: fd03be0e-a4c0-421f-9dd7-1bddc9dece65 +title: JavaScript Prototypes +--- + +# Description + +A prototype can be seen as an [object](20200826201605-objects) another +object extends. + +# Syntax + +``` javascript +let protoRabbit = { + speak(line) { + console.log(`The ${this.type} rabbit says '${line}'`); // : The killer rabbit says 'SKREEEE!' + }, +}; +let killerRabbit = Object.create(protoRabbit); +killerRabbit.type = "killer"; +killerRabbit.speak("SKREEEE!"); +``` + +# Object.prototype + +Most objects in JavaScript eventually extend `Object.prototype` through +parent prototype objects or directly, which provides a bunch of default +methods[^1]. + +``` javascript +console.log(Object.getPrototypeOf({}) == Object.prototype); // true +console.log(Object.getPrototypeOf(Object.prototype)); // null +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113092454-javascript_symbols.md b/content/wiki/20201113092454-javascript_symbols.md new file mode 100644 index 0000000..8a38790 --- /dev/null +++ b/content/wiki/20201113092454-javascript_symbols.md @@ -0,0 +1,92 @@ +--- +date: 2020-11-13 +id: 1e9f826e-69c6-4a52-8cf8-135abc082fb3 +title: JavaScript Symbols +--- + +- [JavaScript Symbol Prototype + Methods](20201116101443-javascript_symbol_prototype_methods) + +# Description + +These are tokens that serve as unique IDs. You create symbols via the +factory function `Symbol()` (which is loosely similar to +[string](20200922164551-strings) returning strings if called as a +function). + +# Syntax + +``` javascript +const symbol1 = Symbol(); +``` + +## Add a description + +``` javascript +const tralala = Symbol('tralala') +console.log(tralala) // Symbol(tralala) +``` + +## Convert to string + +``` javascript +const tralala = Symbol('tralala') +console.log(String(tralala)) // `Symbol(tralala)` +``` + +## Every Symbol is unique + +``` javascript +console.log(Symbol() === Symbol()) // false +``` + +## Property keys + +``` javascript +const KEY = Symbol(); +const obj = {}; + +obj[KEY] = 123; +console.log(obj[KEY]); // 123 +``` + +``` javascript +const FOO = Symbol(); +const obj = { + [FOO]() { + return 'bar'; + } +}; +console.log(obj[FOO]()); // bar +``` + +# Use as reserved inherited method names + +If for some bizarre reason you want to use reserved inherited method +names yourself (like toString) you can with Symbols. + +``` javascript +const toStringSymbol = Symbol("toString"); +Array.prototype[toStringSymbol] = function() { + return `${this.length} cm of blue yarn`; +}; + +console.log([1, 2].toString()); //1, 2 +console.log([1, 2][toStringSymbol]()); // 2 cm of blue yarn +``` + +# Expressions + +Symbols can also be used in [object](20200826201605-objects) expressions +and [classes](20201008090316-class_notation). + +``` javascript +const toStringSymbol = Symbol("toString"); + +let stringObject = { + [toStringSymbol]() { + return "a jute rope"; + }, +}; +console.log(stringObject[toStringSymbol]()); // a jute rope +``` diff --git a/content/wiki/20201113092902-javascript_primitives.md b/content/wiki/20201113092902-javascript_primitives.md new file mode 100644 index 0000000..7b6d394 --- /dev/null +++ b/content/wiki/20201113092902-javascript_primitives.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-13 +id: 78fe3d34-0c03-471c-9c4f-d9d919974b7d +title: JavaScript Primitives +--- + +- [Symbols](20201113092454-javascript_symbols) diff --git a/content/wiki/20201113093204-javascript_object_prototype_methods.md b/content/wiki/20201113093204-javascript_object_prototype_methods.md new file mode 100644 index 0000000..10dc3e4 --- /dev/null +++ b/content/wiki/20201113093204-javascript_object_prototype_methods.md @@ -0,0 +1,54 @@ +--- +date: 2020-11-13 +id: 2c9b94b2-a652-42d7-97ee-731686d29e58 +title: JavaScript Object Prototype Methods +--- + +# Description + +JavaScript [objects](20200826201605-objects) have methods. + +# Syntax + +## Basic syntax + +Objects can also have methods + +``` javascript +let robot = {}; +robot.speak = function(name) { + console.log(`${name} is alive!`) +} + +robot.speak("Johnny 5") +``` + +## Properties + +Of course methods can use object properties and functions can be passed +as properties + +``` javascript +let robot = {name: "Johnny 5", speak}; +function speak(state) { + console.log(`${this.name} is ${state}!`) +} + +robot.speak("alive") +``` + +## This + +`this` parameter can also be passed explicitly using a functions `call` +method, if that's socially acceptable in your culture: + +``` javascript +let robot = {name: "Johnny 5"}; + +function speak(state) { + console.log(`${this.name} is ${state}!`) +} + +speak.call(robot, "alive") + +``` diff --git a/content/wiki/20201113093613-javascript_object_keywords.md b/content/wiki/20201113093613-javascript_object_keywords.md new file mode 100644 index 0000000..cd8cec9 --- /dev/null +++ b/content/wiki/20201113093613-javascript_object_keywords.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-13 +id: 1daece10-b71b-420c-889e-18dc1933b516 +title: JavaScript Object Keywords +--- + +- [new](20201113093910-javascript_new_keyword) diff --git a/content/wiki/20201113093910-javascript_new_keyword.md b/content/wiki/20201113093910-javascript_new_keyword.md new file mode 100644 index 0000000..e5bfef8 --- /dev/null +++ b/content/wiki/20201113093910-javascript_new_keyword.md @@ -0,0 +1,28 @@ +--- +date: 2020-11-13 +id: 32b0031a-0830-4e8c-a39c-3bf6d8791f84 +title: JavaScript New Keyword +--- + +# Description + +When you put the keyword `new` in front of a function call, the function +is treated as a constructor. An [object](20200826201605-objects) with +the proper [prototype](20201113091424-javascript_prototypes) is +automatically created, bound to `this` in the function and returned at +the end of the function. This allows you to do OO type stuff. + +# Syntax + +``` javascript +function Rabbit(type) { + this.type = type +} +Rabbit.prototype.speak = function(line) { + console.log(`The ${this.type} rabbit says '${line}'`) +}; + +let weirdRabbit = new Rabbit("weird") + +weirdRabbit.speak("I want carrots!") +``` diff --git a/content/wiki/20201113094246-javascript_instanceof_operator.md b/content/wiki/20201113094246-javascript_instanceof_operator.md new file mode 100644 index 0000000..c5ebae6 --- /dev/null +++ b/content/wiki/20201113094246-javascript_instanceof_operator.md @@ -0,0 +1,41 @@ +--- +date: 2020-11-13 +id: 54c58f54-526f-4838-92c5-1a70d6b17a3c +title: JavaScript Instanceof Operator +--- + +# Description + +Sometimes you want to know whether an [object](20200826201605-objects) +was derived from a specific [class](20201008090316-class_notation). To +do this one can use the `instanceof` +[operator](20200613170705-operators_in_javascript). + +# Syntax + +``` javascript +class Parent { + constructor(name, parentChild = "Parent") { + this.parentChild = parentChild; + this.name = name; + } + + speak(line) { + console.log(`${this.parentChild} ${this.name} says '${line}'`); + } +} + +class Child extends Parent { + constructor(name) { + super(name, "Child"); + } +} + +let parent = new Parent("Father"); +let child = new Child("Gregory"); + +console.log(parent instanceof Parent); // true +console.log(parent instanceof Child); // false +console.log(child instanceof Parent); // true +console.log(child instanceof Child); // true +``` diff --git a/content/wiki/20201113094652-javascript_delete_operator.md b/content/wiki/20201113094652-javascript_delete_operator.md new file mode 100644 index 0000000..1732642 --- /dev/null +++ b/content/wiki/20201113094652-javascript_delete_operator.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-13 +id: aed94d48-374c-4f3d-8dca-b6e4b3f9ae83 +title: JavaScript Delete Operator +--- + +# Description + +The `delete` operator deletes a binding (duh). + +# Syntax + +``` javascript +let anObject = { left: 1, right: 2 }; +console.log(anObject.left); // 1 + +delete anObject.left; + +console.log(anObject.left); // undefined +console.log("left" in anObject); // false +console.log("right" in anObject); // true +``` diff --git a/content/wiki/20201113095226-object_keys.md b/content/wiki/20201113095226-object_keys.md new file mode 100644 index 0000000..b256ed8 --- /dev/null +++ b/content/wiki/20201113095226-object_keys.md @@ -0,0 +1,16 @@ +--- +date: 2020-11-13 +id: e398afb7-a05b-4780-a3fb-8445f4196c31 +title: Object.keys +--- + +# Description + +`Object.keys` returns the [object](20200826201605-objects) property +names as an array of strings + +# Syntax + +``` javascript +console.log(Object.keys({x: 0, y: 0, z: 2})); +``` diff --git a/content/wiki/20201113095244-object_assign.md b/content/wiki/20201113095244-object_assign.md new file mode 100644 index 0000000..6cd1c63 --- /dev/null +++ b/content/wiki/20201113095244-object_assign.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-13 +id: b7bd3cef-b42a-4f96-8e4c-b0c75c1e86e3 +title: Object.assign +--- + +# Description + +`Object.assign` copies all properties from one +[object](20200826201605-objects) into another + +# Syntax + +``` javascript +let objectA = { a: 1, b: 2 }; +Object.assign(objectA, { b: 3, c: 4 }); +console.log(objectA); +``` diff --git a/content/wiki/20201113095300-object_is.md b/content/wiki/20201113095300-object_is.md new file mode 100644 index 0000000..ddbcf5f --- /dev/null +++ b/content/wiki/20201113095300-object_is.md @@ -0,0 +1,17 @@ +--- +date: 2020-11-13 +id: 5af724a3-745d-45a2-9d5f-e62dc9a22264 +title: Object.is +--- + +# Description + +`Object.is` provides a way of comparing values that's more precise than +`===` + +``` javascript +console.log(NaN === NaN) // false +console.log(Object.is(NaN, NaN)) //true +console.log(-0 === +0) // true +console.log(Object.is(-0, +0)) // false +``` diff --git a/content/wiki/20201113102048-object_entries.md b/content/wiki/20201113102048-object_entries.md new file mode 100644 index 0000000..7a13fe2 --- /dev/null +++ b/content/wiki/20201113102048-object_entries.md @@ -0,0 +1,30 @@ +--- +date: 2020-11-13 +id: 55435d35-26e1-460b-a683-ef346c9972a8 +title: Object.entries +--- + +# Description + +Returns [object](20200826201605-objects) properties as key / value +pairs. Can be used with [maps](20201012093745-javascript_maps) as well. +It does the opposite of +[Object.fromEntries](20201116095124-object_fromentries). + +# Syntax + +``` javascript +console.log(Object.entries({ one: 1, two: 2 })); // [['one', 1], ['two', 2]] +``` + +## Maps + +``` javascript +let map = new Map( + Object.entries({ + one: 1, + two: 2, + }) +); +console.log(JSON.stringify([...map])); // [["one", 1], ["two", 2]] +``` diff --git a/content/wiki/20201113102106-object_values.md b/content/wiki/20201113102106-object_values.md new file mode 100644 index 0000000..39b46f3 --- /dev/null +++ b/content/wiki/20201113102106-object_values.md @@ -0,0 +1,15 @@ +--- +date: 2020-11-13 +id: 2e9254e9-0f90-404e-8f94-0b92d8355a0d +title: Object.values +--- + +# Description + +Returns [object](20200826201605-objects) values + +# Syntax + +``` javascript +console.log(Object.values({ one: 1, two: 2 })); // [1, 2] +``` diff --git a/content/wiki/20201113102125-object_getownpropertydescriptors.md b/content/wiki/20201113102125-object_getownpropertydescriptors.md new file mode 100644 index 0000000..3f161d5 --- /dev/null +++ b/content/wiki/20201113102125-object_getownpropertydescriptors.md @@ -0,0 +1,34 @@ +--- +date: 2020-11-13 +id: 6383dfcd-c925-4d33-8338-2da22edf7ef8 +title: Object.getOwnPropertyDescriptors +--- + +# Description + +Returns property descriptors of all known properties of an +[object](20200826201605-objects). + +# Syntax + +``` javascript +const obj = { + [Symbol("foo")]: 123, + get bar() { + return "abc"; + }, +}; +console.log(Object.getOwnPropertyDescriptors(obj)); + +// Output: +// { [Symbol('foo')]: +// { value: 123, +// writable: true, +// enumerable: true, +// configurable: true }, +// bar: +// { get: [Function: bar], +// set: undefined, +// enumerable: true, +// configurable: true } } +``` diff --git a/content/wiki/20201113103917-javascript_array_functions.md b/content/wiki/20201113103917-javascript_array_functions.md new file mode 100644 index 0000000..5341f01 --- /dev/null +++ b/content/wiki/20201113103917-javascript_array_functions.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-13 +id: 5b9bd5a3-5440-4217-a064-ea6f932ea6c1 +title: JavaScript Array Functions +--- + +- [Array.from()](20201113105832-array_from) +- [Array.of()](20201113105847-array_of) diff --git a/content/wiki/20201113104217-array_prototype_fill.md b/content/wiki/20201113104217-array_prototype_fill.md new file mode 100644 index 0000000..1798f77 --- /dev/null +++ b/content/wiki/20201113104217-array_prototype_fill.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-13 +id: 78535304-014d-4b91-9e80-faf905028338 +title: Array.prototype.fill() +--- + +# Syntax + +``` javascript +const arr2 = new Array(2).fill(undefined); + // [undefined, undefined] +``` diff --git a/content/wiki/20201113104240-array_prototype_copywithin.md b/content/wiki/20201113104240-array_prototype_copywithin.md new file mode 100644 index 0000000..1c49d59 --- /dev/null +++ b/content/wiki/20201113104240-array_prototype_copywithin.md @@ -0,0 +1,24 @@ +--- +date: 2020-11-13 +id: 5b058b90-1a05-4c2f-a64a-a56d3c768191 +title: Array.prototype.copyWithin() +--- + +# Description + +This copies the elements whose indices are in the range \[start,end) to +index target and subsequent indices. If the two index ranges overlap, +care is taken that all source elements are copied before they are +overwritten. I am confused as to how this is in any way useful. + +# Syntax + +``` typescript +Array.prototype.copyWithin(target : number, + start : number, end = this.length) : This +``` + +``` javascript +const arr = [0,1,2,3]; +console.log(arr.copyWithin(2, 0, 2)) // [0, 1, 0, 1] +``` diff --git a/content/wiki/20201113104332-array_prototype_findindex.md b/content/wiki/20201113104332-array_prototype_findindex.md new file mode 100644 index 0000000..9905639 --- /dev/null +++ b/content/wiki/20201113104332-array_prototype_findindex.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-13 +id: 77f7c158-fbf0-48a6-a1e6-681747e5e2f0 +title: Array.prototype.findIndex() +--- + +# Syntax + +``` javascript +console.log([6, -6, 8].findIndex((x) => x < 0)); // 1 +``` diff --git a/content/wiki/20201113104352-array_prototype_find.md b/content/wiki/20201113104352-array_prototype_find.md new file mode 100644 index 0000000..2355047 --- /dev/null +++ b/content/wiki/20201113104352-array_prototype_find.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-13 +id: 0b983a9b-2314-43a8-bd48-62eea3772821 +title: Array.prototype.find() +--- + +# Syntax + +``` javascript +console.log([6, -6, 8].find(x => x < 0)) // -6 +``` diff --git a/content/wiki/20201113104423-array_prototype_entries.md b/content/wiki/20201113104423-array_prototype_entries.md new file mode 100644 index 0000000..2c903fa --- /dev/null +++ b/content/wiki/20201113104423-array_prototype_entries.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-13 +id: 3b9f351b-0109-4c94-80e4-af3ac83542e6 +title: Array.prototype.entries() +--- + +# Syntax + +``` javascript +console.log(Array.from(['a', 'b'].entries())) // [ [ 0, 'a' ], [ 1, 'b' ] ] +``` diff --git a/content/wiki/20201113104438-array_prototype_values.md b/content/wiki/20201113104438-array_prototype_values.md new file mode 100644 index 0000000..12581ff --- /dev/null +++ b/content/wiki/20201113104438-array_prototype_values.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-13 +id: e04ce909-2885-406b-8e0e-e5846354ce86 +title: Array.prototype.values() +--- + +# Syntax + +``` javascript +console.log(Array.from(['a', 'b'].values())) // ['a', 'b'] +``` diff --git a/content/wiki/20201113104454-array_prototype_keys.md b/content/wiki/20201113104454-array_prototype_keys.md new file mode 100644 index 0000000..dddcf5b --- /dev/null +++ b/content/wiki/20201113104454-array_prototype_keys.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-13 +id: c9e2a406-1c26-4c8d-a240-974290a3eeaa +title: Array.prototype.keys() +--- + +# Syntax + +``` javascript +console.log(Array.from(['a', 'b'].keys())) // [0, 1] +``` diff --git a/content/wiki/20201113104552-array_search_prototype_methods.md b/content/wiki/20201113104552-array_search_prototype_methods.md new file mode 100644 index 0000000..eed9108 --- /dev/null +++ b/content/wiki/20201113104552-array_search_prototype_methods.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-13 +id: ce59ae91-4c0b-44f6-9443-0fe2518c39ea +title: Array Search Prototype Methods +--- + +- [Array.prototype.findIndex()](20201113104332-array_prototype_findindex) +- [Array.prototype.find()](20201113104352-array_prototype_find) diff --git a/content/wiki/20201113104619-array_iteration_prototype_methods.md b/content/wiki/20201113104619-array_iteration_prototype_methods.md new file mode 100644 index 0000000..f9796bb --- /dev/null +++ b/content/wiki/20201113104619-array_iteration_prototype_methods.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-13 +id: b442cedc-1746-4c9d-949c-f382e2b8aba6 +title: Array Iteration Prototype Methods +--- + +- [Array.prototype.entries()](20201113104423-array_prototype_entries) +- [Array.prototype.values()](20201113104438-array_prototype_values) +- [Array.prototype.keys()](20201113104454-array_prototype_keys) diff --git a/content/wiki/20201113105707-array_prototype_includes.md b/content/wiki/20201113105707-array_prototype_includes.md new file mode 100644 index 0000000..db37e66 --- /dev/null +++ b/content/wiki/20201113105707-array_prototype_includes.md @@ -0,0 +1,16 @@ +--- +date: 2020-11-13 +id: d5d1956b-d2f4-4cff-bed9-40900f3e1bae +title: Array.prototype.includes() +--- + +# Description + +Tells you if array includes a certain element: + +# Syntax + +``` javascript +console.log(["a", "b", "c"].includes("a")); // true +console.log(["a", "b", "c"].includes("d")); // false +``` diff --git a/content/wiki/20201113105832-array_from.md b/content/wiki/20201113105832-array_from.md new file mode 100644 index 0000000..d62f3a3 --- /dev/null +++ b/content/wiki/20201113105832-array_from.md @@ -0,0 +1,23 @@ +--- +date: 2020-11-13 +id: 5ec66270-20b0-466e-85ea-dd7472a84880 +title: Array.from() +--- + +# Syntax + +``` javascript +const arr2 = Array.from(arguments); +``` + +If a value is [iterable](20201014092625-javascript_iterables) (as all +Array-like DOM data structure are by now), you can also use the +[spread](20201014094144-spread) operator (…) to convert it to an +[Array](20200826201029-arrays): + +``` javascript +const arr1 = [...'abc']; + // ['a', 'b', 'c'] +const arr2 = [...new Set().add('a').add('b')]; + // ['a', 'b'] +``` diff --git a/content/wiki/20201113105847-array_of.md b/content/wiki/20201113105847-array_of.md new file mode 100644 index 0000000..75e8786 --- /dev/null +++ b/content/wiki/20201113105847-array_of.md @@ -0,0 +1,15 @@ +--- +date: 2020-11-13 +id: 5952e353-e25e-4a74-95ce-8099891212c5 +title: Array.of() +--- + +# Description + +This returns an array of the passed parameters + +# Syntax + +``` javascript +console.log(Array.of(1, 2, 3, 4)) // [1, 2, 3, 4] +``` diff --git a/content/wiki/20201113111815-es2019.md b/content/wiki/20201113111815-es2019.md new file mode 100644 index 0000000..e9a071e --- /dev/null +++ b/content/wiki/20201113111815-es2019.md @@ -0,0 +1,41 @@ +--- +date: 2020-11-13 +id: 7aa626ee-1b0b-4d7c-8e11-751f8b9cac1f +title: ES2019 +--- + +# Array + +## Prototype methods + +- [Array.prototype.flatMap()](20201113112058-array_prototype_flatmap) +- [Array.prototype.flat()](20201113112029-array_prototype_flat) + +### Sort + +- [.sort() is guaranteed to be + stable](20201116155810-sort_is_guaranteed_to_be_stable) + +# Control flow + +- [Optional Catch + Binding](20201116154824-javascript_optional_catch_binding) + +# Objects + +## Functions + +- [Object.fromEntries](20201116095124-object_fromentries) + +# Strings + +## String Prototype methods + +- [trimStart](20201116100205-trimstart) +- [trimEnd](20201116100239-trimend) + +# Symbols + +## Symbol Prototype methods + +- [Symbol.prototype.description](20201116101509-symbol_prototype_description) diff --git a/content/wiki/20201113112029-array_prototype_flat.md b/content/wiki/20201113112029-array_prototype_flat.md new file mode 100644 index 0000000..c560fb6 --- /dev/null +++ b/content/wiki/20201113112029-array_prototype_flat.md @@ -0,0 +1,23 @@ +--- +date: 2020-11-13 +id: caa62af1-768f-4ca7-95c2-ba38c703101d +title: Array.prototype.flat() +--- + +# Description + +Flattens an [array](20200826201029-arrays). + +# Type Signature + +``` typescript +.flat(depth = 1): any[] +``` + +# Syntax + +``` javascript +console.log([1, 2, [3, 4], [[5, 6]]].flat(0)); // [ 1, 2, [ 3, 4 ], [ [ 5, 6 ] ] ] +console.log([1, 2, [3, 4], [[5, 6]]].flat(1)); // [ 1, 2, 3, 4, [ 5, 6 ] ] +console.log([1, 2, [3, 4], [[5, 6]]].flat(2)); // [ 1, 2, 3, 4, 5, 6 ] +``` diff --git a/content/wiki/20201113112058-array_prototype_flatmap.md b/content/wiki/20201113112058-array_prototype_flatmap.md new file mode 100644 index 0000000..684142a --- /dev/null +++ b/content/wiki/20201113112058-array_prototype_flatmap.md @@ -0,0 +1,32 @@ +--- +date: 2020-11-13 +id: 1aa59b86-bbea-4eb7-beac-67c7e1460ecf +title: Array.prototype.flatMap() +--- + +# Description + +Is the same as calling [JavaScript Maps](20201012093745-javascript_maps) +and then flattening the result. Ie: + +``` javascript +arr.map(func).flat(1) +``` + +# Type Signature + +``` typescript +.flatMap( + callback: (value: T, index: number, array: T[]) => U|Array, + thisValue?: any +): U[] +``` + +# Syntax + +``` javascript +console.log(["a", "b", "c"].flatMap((x) => x)); // [ 'a', 'b', 'c' ] +console.log(["a", "b", "c"].flatMap((x) => [x])); // [ 'a', 'b', 'c' ] +console.log(["a", "b", "c"].flatMap((x) => [[x]])); // [ [ 'a' ], [ 'b' ], [ 'c' ] ] +console.log(["a", "b", "c"].flatMap((x, i) => new Array(i + 1).fill(x))); // [ 'a', 'b', 'b', 'c', 'c', 'c' ] +``` diff --git a/content/wiki/20201113113141-array_prototype_map.md b/content/wiki/20201113113141-array_prototype_map.md new file mode 100644 index 0000000..f28be8a --- /dev/null +++ b/content/wiki/20201113113141-array_prototype_map.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-13 +id: d8cdd418-4d65-4814-b362-9db4a6730030 +title: Array.prototype.map() +--- + +# Description + +`map()` creates a new array populated with the results of calling a +passed function on every element in the calling array. + +# Syntax + +``` javascript +const array = [1, 2, 3, 4]; +const map1 = array.map((x) => x * 2); + +console.log(map1); // [(2, 4, 6, 8)] +``` diff --git a/content/wiki/20201113115201-php_string_functions.md b/content/wiki/20201113115201-php_string_functions.md new file mode 100644 index 0000000..9d6e443 --- /dev/null +++ b/content/wiki/20201113115201-php_string_functions.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-13 +id: ed9de386-a191-4fd8-a842-bb7d55df52a0 +title: PHP string functions +--- + +# Checks + +- [str~contains~()](20201113115231-str_contains) +- [str~startswith~()](20201113115424-str_starts_with) +- [str~endswith~()](20201113115452-str_ends_with) diff --git a/content/wiki/20201113115231-str_contains.md b/content/wiki/20201113115231-str_contains.md new file mode 100644 index 0000000..8e3351c --- /dev/null +++ b/content/wiki/20201113115231-str_contains.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-13 +id: 01a0e800-3398-490b-bbb1-3abc80fb198c +title: str~contains~() +--- + +# Description + +str~contains~()[^1] tells us if string contains other string. + +# Syntax + +``` php +if (str_contains('Lululu I've got some apples, 'apples')) { /* … */ } +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113115424-str_starts_with.md b/content/wiki/20201113115424-str_starts_with.md new file mode 100644 index 0000000..5fa8984 --- /dev/null +++ b/content/wiki/20201113115424-str_starts_with.md @@ -0,0 +1,20 @@ +--- +date: 2020-11-13 +id: 264796d2-49ae-42fc-9d9d-aeea84343ef1 +title: str~startswith~() +--- + +# Description + +Checks if string starts with other string. Opposite of +[str~endswith~()](20201113115452-str_ends_with). See RFC[^1]. + +# Syntax + +``` php +str_starts_with('haystack', 'hay') // true +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113115452-str_ends_with.md b/content/wiki/20201113115452-str_ends_with.md new file mode 100644 index 0000000..0091546 --- /dev/null +++ b/content/wiki/20201113115452-str_ends_with.md @@ -0,0 +1,21 @@ +--- +date: 2020-11-13 +id: 43cb053d-03b0-4845-a804-5e34da5d8db5 +title: str~endswith~() +--- + +# Description + +Check if string ends with other string. Opposite of +[str~startswith~()](20201113115424-str_starts_with). See RFC[^1] for +more details. + +# Syntax + +``` php +str_ends_with('haystack', 'stack') // true +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113115907-php_type_functions.md b/content/wiki/20201113115907-php_type_functions.md new file mode 100644 index 0000000..0257cfa --- /dev/null +++ b/content/wiki/20201113115907-php_type_functions.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-13 +id: 9e217634-5bde-4c98-ba86-9b63eb19b2e9 +title: PHP type functions +--- + +- [get~debugtype~()](20201113115939-get_debug_type) diff --git a/content/wiki/20201113115939-get_debug_type.md b/content/wiki/20201113115939-get_debug_type.md new file mode 100644 index 0000000..f9abd7a --- /dev/null +++ b/content/wiki/20201113115939-get_debug_type.md @@ -0,0 +1,29 @@ +--- +date: 2020-11-13 +id: 62a9d222-f5a2-4131-8de7-be1b071cab26 +title: get~debugtype~() +--- + +# Description + +Returns the variable type. Differnce with `getttype()` is that +`get_debug_type()` is more specific. See RFC[^1]. + +# Syntax + +``` php +namespace Foo; + +class Bar +{ +} + +$bar = new Bar(); + +echo gettype($bar)."\n"; // Object +echo get_debug_type($bar); // Foo\Bar +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113120212-php_resource_functions.md b/content/wiki/20201113120212-php_resource_functions.md new file mode 100644 index 0000000..3d783d3 --- /dev/null +++ b/content/wiki/20201113120212-php_resource_functions.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-13 +id: 91bd46af-67dc-402f-ad3a-f3096eda5e7d +title: PHP resource functions +--- + +- [get~resourceid~()](20201113120246-get_resource_id) diff --git a/content/wiki/20201113120246-get_resource_id.md b/content/wiki/20201113120246-get_resource_id.md new file mode 100644 index 0000000..b1ca2fb --- /dev/null +++ b/content/wiki/20201113120246-get_resource_id.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-13 +id: bc32aee3-3e3c-42e8-b56e-8e8e7f3a8d39 +title: get~resourceid~() +--- + +# Description + +Returns a resource id as an integer. See PR[^1] + +# Syntax + +``` php +$resourceId = get_resource_id($resource); +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113121741-php_expressions.md b/content/wiki/20201113121741-php_expressions.md new file mode 100644 index 0000000..a3e1c74 --- /dev/null +++ b/content/wiki/20201113121741-php_expressions.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-13 +id: efe804b8-fbb0-4644-ab98-db58a1ebaf2b +title: PHP expressions +--- + +- [Match expression](20201113121813-match_expression) +- [Switch expression](20201113122000-switch_expression) diff --git a/content/wiki/20201113121813-match_expression.md b/content/wiki/20201113121813-match_expression.md new file mode 100644 index 0000000..3f340c2 --- /dev/null +++ b/content/wiki/20201113121813-match_expression.md @@ -0,0 +1,115 @@ +--- +date: 2020-11-13 +id: 0d9d39fc-149c-4190-a06d-1de455c930a4 +title: Match expression +--- + +# Description + +Match expressions[^1] are similar to +[switch](20201113122000-switch_expression), but with safer semantics and +the ability to return values. + +# Syntax + +``` php +// After +$statement = match ($this->lexer->lookahead['type']) { + Lexer::T_SELECT => $this->SelectStatement(), + Lexer::T_UPDATE => $this->UpdateStatement(), + Lexer::T_DELETE => $this->DeleteStatement(), + default => $this->syntaxError('SELECT, UPDATE or DELETE'), +}; +``` + +## Return value + +``` php +switch (1) { + case 0: + $result = 'Foo'; + break; + case 1: + $result = 'Bar'; + break; + case 2: + $result = 'Baz'; + break; +} + +echo $result; +//> Bar + +echo match (1) { + 0 => 'Foo', + 1 => 'Bar', + 2 => 'Baz', +}; +//> Bar +``` + +## No type coercion + +``` php +switch ('foo') { + case 0: + $result = "Oh no!\n"; + break; + case 'foo': + $result = "This is what I expected\n"; + break; +} +echo $result; +//> Oh no! + +echo match ('foo') { + 0 => "Oh no!\n", + 'foo' => "This is what I expected\n", +}; +//> This is what I expected +``` + +## No fallthrough + +``` php +switch ($pressedKey) { + case Key::RETURN_: + save(); + // Oops, forgot the break + case Key::DELETE: + delete(); + break; +} + +match ($pressedKey) { + Key::RETURN_ => save(), + Key::DELETE => delete(), +}; + +echo match ($x) { + 1, 2 => 'Same for 1 and 2', + 3, 4 => 'Same for 3 and 4', +}; +``` + +## Exhaustiveness + +``` php +switch ($operator) { + case BinaryOperator::ADD: + $result = $lhs + $rhs; + break; +} + +// Forgot to handle BinaryOperator::SUBTRACT + +$result = match ($operator) { + BinaryOperator::ADD => $lhs + $rhs, +}; + +// Throws when $operator is BinaryOperator::SUBTRACT +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113122000-switch_expression.md b/content/wiki/20201113122000-switch_expression.md new file mode 100644 index 0000000..f47b6e1 --- /dev/null +++ b/content/wiki/20201113122000-switch_expression.md @@ -0,0 +1,31 @@ +--- +date: 2020-11-13 +id: f9e3afdc-2d87-4ba2-a9de-758e403bff56 +title: Switch expression +--- + +# Description + +Probably a better idea to use [match](20201113121813-match_expression). + +# Syntax + +``` php +switch ($this->lexer->lookahead['type']) { + case Lexer::T_SELECT: + $statement = $this->SelectStatement(); + break; + + case Lexer::T_UPDATE: + $statement = $this->UpdateStatement(); + break; + + case Lexer::T_DELETE: + $statement = $this->DeleteStatement(); + break; + + default: + $this->syntaxError('SELECT, UPDATE or DELETE'); + break; +} +``` diff --git a/content/wiki/20201113122505-php_types.md b/content/wiki/20201113122505-php_types.md new file mode 100644 index 0000000..2eedb62 --- /dev/null +++ b/content/wiki/20201113122505-php_types.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-13 +id: 60007d1e-e543-46a0-bf43-509ed0bf96d1 +title: PHP Types +--- + +- [Union Type](20201109133923-php_union_type) +- [Mixed Type](20201113122959-php_mixed_type) diff --git a/content/wiki/20201113122801-php_functions.md b/content/wiki/20201113122801-php_functions.md new file mode 100644 index 0000000..fc43682 --- /dev/null +++ b/content/wiki/20201113122801-php_functions.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-13 +id: 40b230dd-eb86-408b-8dbb-098a19ebaf93 +title: PHP functions +--- + +- [Resource Functions](20201113120212-php_resource_functions) +- [String Functions](20201113115201-php_string_functions) +- [Type Functions](20201113115907-php_type_functions) diff --git a/content/wiki/20201113122959-php_mixed_type.md b/content/wiki/20201113122959-php_mixed_type.md new file mode 100644 index 0000000..413ef8a --- /dev/null +++ b/content/wiki/20201113122959-php_mixed_type.md @@ -0,0 +1,14 @@ +--- +date: 2020-11-13 +id: 13fec466-6379-452f-abdb-3360b69adcb8 +title: PHP Mixed Type +--- + +# Description + +mixed[^1] is the PHP equivalent to +[JavaScript's](20200613170905-javascript) any type. + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113123224-php_objects.md b/content/wiki/20201113123224-php_objects.md new file mode 100644 index 0000000..9416679 --- /dev/null +++ b/content/wiki/20201113123224-php_objects.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-13 +id: 0db5ee45-e14e-44ff-97b3-5b9320ad81cb +title: PHP Objects +--- + +- [DateTime](20201113123254-datetime) diff --git a/content/wiki/20201113123254-datetime.md b/content/wiki/20201113123254-datetime.md new file mode 100644 index 0000000..cb48bd2 --- /dev/null +++ b/content/wiki/20201113123254-datetime.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-13 +id: dcb3bb34-214e-4f36-8da4-d4f0771ec1e5 +title: DateTime +--- + +# Methods + +- [createFromInterface()](20201113123327-createfrominterface) +- [createFromImmutable()](20201113123648-createfromimmutable) diff --git a/content/wiki/20201113123327-createfrominterface.md b/content/wiki/20201113123327-createfrominterface.md new file mode 100644 index 0000000..582a427 --- /dev/null +++ b/content/wiki/20201113123327-createfrominterface.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-13 +id: 6e9abc7a-fef2-4450-9694-8311eb70d7cf +title: createFromInterface() +--- + +# Description + +Similar to [createFromImmutable()](20201113123648-createfromimmutable), +but this method creates a date from any object that uses +`DateTimeInterface` + +# Syntax + +``` php +DateTime::createFromInterface(DateTimeInterface $other); +DateTimeImmutable::createFromInterface(DateTimeInterface $other); +``` diff --git a/content/wiki/20201113123648-createfromimmutable.md b/content/wiki/20201113123648-createfromimmutable.md new file mode 100644 index 0000000..b82f95a --- /dev/null +++ b/content/wiki/20201113123648-createfromimmutable.md @@ -0,0 +1,17 @@ +--- +date: 2020-11-13 +id: 984344e1-ee68-4475-b792-71f2a6e0b766 +title: createFromImmutable() +--- + +# Description + +Similar to [createFromInterface()](20201113123327-createfrominterface), +but this function creates a `DateTime` object from a `DateTimeImmutable` +one. + +# Syntax + +``` php +DateTime::createFromImmutable(new DateTimeImmutable()) +``` diff --git a/content/wiki/20201113172025-symfony_5_0.md b/content/wiki/20201113172025-symfony_5_0.md new file mode 100644 index 0000000..5d891eb --- /dev/null +++ b/content/wiki/20201113172025-symfony_5_0.md @@ -0,0 +1,65 @@ +--- +date: 2020-11-13 +id: 571452e9-b81e-42a3-95a2-306375073bc5 +title: Symfony 5.0 +--- + +# Components + +## Mailer + +- [Signing and Encrypting + Messages](20201113173159-signing_and_encrypting_messages) + +## Mime + +- [Notification Emails](20201113174016-notification_emails) + +## Console + +- [Horizontal Tables](20201113180928-horizontal_tables) +- [horizontalTable()](20201113181235-horizontaltable) +- [Definition Lists](20201113181356-definition_lists) + +## HttpFoundation + +- [IP Address Anonymizer](20201113182523-ip_address_anonymizer) + +## String + +- [String Component](20201113183442-string_component) + +# Constraints + +## Type Constraint + +- [Type Constraint Can Be An Array of + Types](20201113172816-type_constraint_can_be_an_array_of_types) + +# Doctrine + +- [Invokable Doctrine Entity + Listeners](20201113180722-invokable_doctrine_entity_listeners) + +# Encryption + +- [Ecrypted Secrets + Management](20201113174444-ecrypted_secrets_management) + +# Event Listeners + +- [Simpler Event Listeners](20201113180227-simpler_event_listeners) + +# Firewalls + +- [Lazy Firewalls](20201113183038-lazy_firewalls) + +# Forms + +## Types + +- [Week Form Type](20201113182753-week_form_type) + +# Password + +- [Password Migrations](20201113181759-password_migrations) diff --git a/content/wiki/20201113172517-type_constraint.md b/content/wiki/20201113172517-type_constraint.md new file mode 100644 index 0000000..5c22392 --- /dev/null +++ b/content/wiki/20201113172517-type_constraint.md @@ -0,0 +1,46 @@ +--- +date: 2020-11-13 +id: 942ca5cd-5ca6-4ec9-9dd6-652a0b791245 +title: Type Constraint +--- + +# Description + +Validates that a given value is of a specific type. This type can be any +of the valid PHP types[^1], any of the PHP ctype functions[^2] (e.g. +alnum, alpha, digit, etc.) and also the FQCN of any class + +# Syntax + +``` php +// src/Entity/Author.php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class Author +{ + /** + * @Assert\Type("Ramsey\Uuid\UuidInterface") + */ + protected $id; + + /** + * @Assert\Type("string") + */ + protected $firstName; + + // ... +} +``` + +# Changelog + +- [Type Constraint Can Be An Array of + Types](20201113172816-type_constraint_can_be_an_array_of_types) + +# Footnotes + +[^1]: + +[^2]: diff --git a/content/wiki/20201113172816-type_constraint_can_be_an_array_of_types.md b/content/wiki/20201113172816-type_constraint_can_be_an_array_of_types.md new file mode 100644 index 0000000..e3560c0 --- /dev/null +++ b/content/wiki/20201113172816-type_constraint_can_be_an_array_of_types.md @@ -0,0 +1,24 @@ +--- +date: 2020-11-13 +id: e8cb1177-6034-441f-a23e-bcdbf5a31fa6 +title: Type Constraint Can Be An Array of Types +--- + +# Syntax + +``` php +// src/Entity/Author.php +namespace App\Entity; + +use Symfony\Component\Validator\Constraints as Assert; + +class Author +{ + // ... + + /** + * @Assert\Type(type={"alpha", "digit"}) + */ + protected $accessCode; +} +``` diff --git a/content/wiki/20201113173159-signing_and_encrypting_messages.md b/content/wiki/20201113173159-signing_and_encrypting_messages.md new file mode 100644 index 0000000..4e2e742 --- /dev/null +++ b/content/wiki/20201113173159-signing_and_encrypting_messages.md @@ -0,0 +1,42 @@ +--- +date: 2020-11-13 +id: 9256ee27-61e2-4c9f-b49c-bc2efe01d528 +title: Signing and Encrypting Messages +--- + +# Description + +Emails can be signed an encrypted using the S/MIME[^1] standard. + +# Syntax + +## Signing + +``` php +use Symfony\Component\Mime\Crypto\SMimeSigner; +use Symfony\Component\Mime\Email; + +$email = (new Email())->from('...')->to('...')->html('...'); + +$signer = new SMimeSigner('/path/to/certificate.crt', '/path/to/certificate-private-key.key'); +$signedEmail = $signer->sign($email); +// now use the Mailer to send this $signedEmail instead of the original $email + +``` + +## Encrypting + +``` php +use Symfony\Component\Mime\Crypto\SMimeEncrypter; +use Symfony\Component\Mime\Email; + +$email = (new Email())->from('...')->to('...')->html('...'); + +$encrypter = new SMimeEncrypter('/path/to/certificate.crt'); +$encryptedEmail = $encrypter->encrypt($email); +// now use the Mailer to send this $encryptedEmail instead of the original $email +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113174016-notification_emails.md b/content/wiki/20201113174016-notification_emails.md new file mode 100644 index 0000000..8f88253 --- /dev/null +++ b/content/wiki/20201113174016-notification_emails.md @@ -0,0 +1,29 @@ +--- +date: 2020-11-13 +id: b6e6c503-c614-4bf3-872a-3a6202e2dbfb +title: Notification Emails +--- + +# Description + +Standardized messages used to send notifications to yourself + +# Syntax + +``` php +use Symfony\Bridge\Twig\Mime\NotificationEmail; + +$email = (new NotificationEmail()) + ->from('fabien@example.com') + ->to('fabien@example.org') + ->subject('My first notification email via Symfony') + ->markdown(<<action('More info?', 'https://example.com/') + ->importance(NotificationEmail::IMPORTANCE_HIGH) +; +``` diff --git a/content/wiki/20201113174255-encryption.md b/content/wiki/20201113174255-encryption.md new file mode 100644 index 0000000..5923038 --- /dev/null +++ b/content/wiki/20201113174255-encryption.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-13 +id: b3ac98d7-046d-4f86-b487-36df5d184718 +title: Encryption +--- + +- [Signing and Encrypting + Messages](20201113173159-signing_and_encrypting_messages) +- [Ecrypted Secrets + Management](20201113174444-ecrypted_secrets_management) diff --git a/content/wiki/20201113174444-ecrypted_secrets_management.md b/content/wiki/20201113174444-ecrypted_secrets_management.md new file mode 100644 index 0000000..5107dd3 --- /dev/null +++ b/content/wiki/20201113174444-ecrypted_secrets_management.md @@ -0,0 +1,54 @@ +--- +date: 2020-11-13 +id: e9ea6e53-c383-4b23-b90c-77cd202f8002 +title: Ecrypted Secrets Management +--- + +# Description + +Encryption based feature to manage secrets. + +# Steps + +## 1. Generate keys to encrypt/decrypt secret + +Uses libsodium[^1] and public key cryptography. + +``` shell +php bin/console secrets:generate-keys +``` + +## 2. Upload private key + +Upload the private key to your remote server using SSH or any other safe +means and store it in the same `config/secrets//` +directory. + +## 3. Create a new secret to store the contents + +``` shell +php bin/console secrets:set DATABASE_URL + +Please type the secret value: +************** + +[OK] Secret "DATABASE_URL" encrypted in "config/secrets/dev/" +you can commit it. +``` + +# Using secret + +Use this new secret as any other normal env var in your configuration +files and Symfony will decrypt the value transparently when needed. + +``` yaml +# config/packages/doctrine.yaml +doctrine: + dbal: + url: "%env(DATABASE_URL)%" + # ... +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113175016-events.md b/content/wiki/20201113175016-events.md new file mode 100644 index 0000000..421860a --- /dev/null +++ b/content/wiki/20201113175016-events.md @@ -0,0 +1,19 @@ +--- +date: 2020-11-13 +id: cdbbd32f-7f21-453d-abbf-f04f8180587b +title: Events +--- + +# Events + +- [ConsoleEvents::SIGNAL](20201117115146-consoleevents_signal) +- [LogoutEvent](20201116133907-logoutevent) + +# Listeners + +- [Event Listeners](20201113175527-event_listeners) + +# Subscribers + +- [Subscribing to events in the micro + kernel](20201109150109-subscribing_to_events_in_the_micro_kernel) diff --git a/content/wiki/20201113175145-listeners.md b/content/wiki/20201113175145-listeners.md new file mode 100644 index 0000000..db057a7 --- /dev/null +++ b/content/wiki/20201113175145-listeners.md @@ -0,0 +1,14 @@ +--- +date: 2020-11-13 +id: 87b446e7-b094-417c-a948-b0bb01955c13 +title: Listeners +--- + +# Events + +- [Event Listeners](20201113175527-event_listeners) + +# Doctrine + +- [Doctrine Entity + Listeners](20201113180551-doctrine_entity_listeners) diff --git a/content/wiki/20201113175249-subscribers.md b/content/wiki/20201113175249-subscribers.md new file mode 100644 index 0000000..9cc6639 --- /dev/null +++ b/content/wiki/20201113175249-subscribers.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-13 +id: 2071b494-c2e9-4443-87bc-a71e1ff97b27 +title: Subscribers +--- + +# Events + +- [Subscribing to events in the micro + kernel](20201109150109-subscribing_to_events_in_the_micro_kernel) diff --git a/content/wiki/20201113175527-event_listeners.md b/content/wiki/20201113175527-event_listeners.md new file mode 100644 index 0000000..ab7fefa --- /dev/null +++ b/content/wiki/20201113175527-event_listeners.md @@ -0,0 +1,20 @@ +--- +date: 2020-11-13 +id: d0882e91-d271-4c96-8d83-16500eadfb85 +title: Event Listeners +--- + +# Syntax + +## Pre Symfony 5.0 + +``` yaml +# config/services.yaml +services: + tags: + - { name: kernel.event_listener, event: kernel.request } +``` + +## Symfony 5.0 + +[Simpler Event Listeners](20201113180227-simpler_event_listeners) diff --git a/content/wiki/20201113180227-simpler_event_listeners.md b/content/wiki/20201113180227-simpler_event_listeners.md new file mode 100644 index 0000000..0527796 --- /dev/null +++ b/content/wiki/20201113180227-simpler_event_listeners.md @@ -0,0 +1,29 @@ +--- +date: 2020-11-13 +id: 0ada3ab8-c8d8-4803-9c7d-7e044533f793 +title: Simpler Event Listeners +--- + +# Syntax + +``` yaml +# config/services.yaml +services: + App\EventListener\MyRequestListener: + tags: + - { name: kernel.event_listener } +``` + +``` php +namespace App\EventListener; + +use Symfony\Component\HttpKernel\Event\RequestEvent; + +final class MyRequestListener +{ + public function __invoke(RequestEvent $event): void + { + // ... + } +} +``` diff --git a/content/wiki/20201113180551-doctrine_entity_listeners.md b/content/wiki/20201113180551-doctrine_entity_listeners.md new file mode 100644 index 0000000..26b12b4 --- /dev/null +++ b/content/wiki/20201113180551-doctrine_entity_listeners.md @@ -0,0 +1,12 @@ +--- +date: 2020-11-13 +id: f966e2d6-6e78-40c5-b8ac-73f3ea4f24fe +title: Doctrine Entity Listeners +--- + +# Syntax + +## Symfony 5.0 + +[Invokable Doctrine Entity +Listeners](20201113180722-invokable_doctrine_entity_listeners) diff --git a/content/wiki/20201113180722-invokable_doctrine_entity_listeners.md b/content/wiki/20201113180722-invokable_doctrine_entity_listeners.md new file mode 100644 index 0000000..ea61e69 --- /dev/null +++ b/content/wiki/20201113180722-invokable_doctrine_entity_listeners.md @@ -0,0 +1,37 @@ +--- +date: 2020-11-13 +id: f5d0ea95-75b4-48e9-99b4-7e420fd40956 +title: Invokable Doctrine Entity Listeners +--- + +# Syntax + +``` php +namespace App\EventListener; + +use App\Entity\User; +use Doctrine\Common\Persistence\Event\LifecycleEventArgs; + +class UserChangedNotifier +{ + public function __invoke(User $user, LifecycleEventArgs $event) + { + // ... + } +} +``` + +``` yaml +services: + # ... + + App\EventListener\UserChangedNotifier: + tags: + - + name: 'doctrine.orm.entity_listener' + entity: 'App\Entity\User' + # before, when not defining the method name, Symfony looked for + # a method called after the event (e.g. 'postUpdate()') Now it + # will also look for an '__invoke()' method + event: 'postUpdate' +``` diff --git a/content/wiki/20201113180928-horizontal_tables.md b/content/wiki/20201113180928-horizontal_tables.md new file mode 100644 index 0000000..45e36b2 --- /dev/null +++ b/content/wiki/20201113180928-horizontal_tables.md @@ -0,0 +1,27 @@ +--- +date: 2020-11-13 +id: f236ec20-fe58-437d-bfe1-a1ed58bcf3e0 +title: Horizontal Tables +--- + +# Syntax + +``` php +$table + ->setHeaders(['ISBN', 'Title', 'Author']) + ->setRows([ + // ... the rows ... + ]) + ->setHorizontal() +; +``` + +# Output + +``` shell ++--------+-----------------+----------------------+-----------------------+--------------------------+ +| ISBN | 99921-58-10-7 | 9971-5-0210-0 | 960-425-059-0 | 80-902734-1-6 | +| Title | Divine Comedy | A Tale of Two Cities | The Lord of the Rings | And Then There Were None | +| Author | Dante Alighieri | Charles Dickens | J. R. R. Tolkien | Agatha Christie | ++--------+-----------------+----------------------+-----------------------+--------------------------+ +``` diff --git a/content/wiki/20201113181152-symfony_style_for_commands.md b/content/wiki/20201113181152-symfony_style_for_commands.md new file mode 100644 index 0000000..b21119d --- /dev/null +++ b/content/wiki/20201113181152-symfony_style_for_commands.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-13 +id: 9d8559b3-c0ea-40c9-99d8-a9af58b9d722 +title: Symfony Style For Commands +--- + +# Methods + +- [horizontalTable()](20201113181235-horizontaltable) diff --git a/content/wiki/20201113181235-horizontaltable.md b/content/wiki/20201113181235-horizontaltable.md new file mode 100644 index 0000000..208c51e --- /dev/null +++ b/content/wiki/20201113181235-horizontaltable.md @@ -0,0 +1,22 @@ +--- +date: 2020-11-13 +id: 5bae3aba-682a-4e09-b6b5-e71fabd8072d +title: horizontalTable() +--- + +# Syntax + +``` php +use Symfony\Component\Console\Style\SymfonyStyle; + +protected function execute(InputInterface $input, OutputInterface $output) +{ + $io = new SymfonyStyle($input, $output); + $io->horizontalTable( + ['ISBN', 'Title', 'Author'], + [ + // ... the rows ... + ] + ); +} +``` diff --git a/content/wiki/20201113181356-definition_lists.md b/content/wiki/20201113181356-definition_lists.md new file mode 100644 index 0000000..48406fd --- /dev/null +++ b/content/wiki/20201113181356-definition_lists.md @@ -0,0 +1,33 @@ +--- +date: 2020-11-13 +id: e745d46a-809d-4c00-ada0-c2b99d1d4007 +title: Definition Lists +--- + +# Syntax + +``` php +use Symfony\Component\Console\Helper\TableSeparator; + +$io->definitionList( + ['Version' => '4.4.0'], + ['Long-Term Support' => 'Yes'], + new TableSeparator(), + 'Timeline', + ['End of maintenance' => '11/2022'], + ['End of life' => '11/2023'] +); +``` + +# Output + +``` shell +-------------------- --------- +Version 4.4.0 +Long-Term Support Yes +-------------------- --------- +Timeline +End of maintenance 11/2022 +End of life 11/2023 +-------------------- --------- +``` diff --git a/content/wiki/20201113181759-password_migrations.md b/content/wiki/20201113181759-password_migrations.md new file mode 100644 index 0000000..45717b3 --- /dev/null +++ b/content/wiki/20201113181759-password_migrations.md @@ -0,0 +1,43 @@ +--- +date: 2020-11-13 +id: 11f17415-46cc-4100-ab3d-4e552dd8886e +title: Password Migrations +--- + +# Description + +Automatically upgrade password hashes by using +`PasswordUpgraderInterface` interface + +# Syntax + +``` yaml +# config/packages/security.yaml +security: + # ... + encoders: + App\Entity\User: + algorithm: 'argon2i' + migrate_from: 'bcrypt' +``` + +``` php +// src/Repository/UserRepository.php +namespace App\Repository; + +// ... +use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; + +class UserRepository extends EntityRepository implements PasswordUpgraderInterface +{ + // ... + + public function upgradePassword(UserInterface $user, string $newEncodedPassword): void + { + // this code is only an example; the exact code will depend on + // your own application needs + $user->setPassword($newEncodedPassword); + $this->getEntityManager()->flush($user); + } +} +``` diff --git a/content/wiki/20201113182438-httpfoundation_component.md b/content/wiki/20201113182438-httpfoundation_component.md new file mode 100644 index 0000000..a5fa08d --- /dev/null +++ b/content/wiki/20201113182438-httpfoundation_component.md @@ -0,0 +1,9 @@ +--- +date: 2020-11-13 +id: 9b8a1375-52e2-4b8b-9373-7b3457a4b194 +title: HttpFoundation Component +--- + +# IpUtils + +- [IP Address Anonymizer](20201113182523-ip_address_anonymizer) diff --git a/content/wiki/20201113182523-ip_address_anonymizer.md b/content/wiki/20201113182523-ip_address_anonymizer.md new file mode 100644 index 0000000..4f1f81a --- /dev/null +++ b/content/wiki/20201113182523-ip_address_anonymizer.md @@ -0,0 +1,23 @@ +--- +date: 2020-11-13 +id: 8a367c4d-c104-41ff-953b-23d5d154028f +title: IP Address Anonymizer +--- + +# Description + +Removes last byte for IPV4 addresses and last 8 bytes for IPV6 + +# Syntax + +``` php +use Symfony\Component\HttpFoundation\IpUtils; + +$ipv4 = '123.234.235.236'; +$anonymousIpv4 = IPUtils::anonymize($ipv4); +// $anonymousIpv4 = '123.234.235.0' + +$ipv6 = '2a01:198:603:10:396e:4789:8e99:890f'; +$anonymousIpv6 = IPUtils::anonymize($ipv6); +// $anonymousIpv6 = '2a01:198:603:10::' +``` diff --git a/content/wiki/20201113182753-week_form_type.md b/content/wiki/20201113182753-week_form_type.md new file mode 100644 index 0000000..b7c4891 --- /dev/null +++ b/content/wiki/20201113182753-week_form_type.md @@ -0,0 +1,34 @@ +--- +date: 2020-11-13 +id: 34002025-52f5-410c-ad48-25a27bbad197 +title: Week Form Type +--- + +# Description + +`WeekType` form field that allows users to modify data that represents a +specific ISO 8601[^1] week number + +# Syntax + +``` php +use Symfony\Component\Form\Extension\Core\Type\WeekType; + +$builder->add('startDateTime', WeekType::class, [ + // use this if you store week numbers as strings ('2011-W17') + 'input' => 'string', + // use this if you store week numbers as arrays (e.g. [2011, 17]) + 'input' => 'array', + + // renders two to write the year and week number + 'widget' => 'text', + // renders a which is properly rendered by most browsers + 'widget' => 'single_text', +]); +``` + +# Footnotes + +[^1]: diff --git a/content/wiki/20201113183038-lazy_firewalls.md b/content/wiki/20201113183038-lazy_firewalls.md new file mode 100644 index 0000000..7060e99 --- /dev/null +++ b/content/wiki/20201113183038-lazy_firewalls.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-13 +id: 70e05930-7411-4ccb-8458-9d10b2ae4720 +title: Lazy Firewalls +--- + +# Syntax + +``` yaml +# config/packages/security.yaml +security: + # ... + firewalls: + main: + pattern: ^/ + anonymous: lazy + # ... +``` diff --git a/content/wiki/20201113183209-symfony_firewalls.md b/content/wiki/20201113183209-symfony_firewalls.md new file mode 100644 index 0000000..f7d5ce2 --- /dev/null +++ b/content/wiki/20201113183209-symfony_firewalls.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-13 +id: 020efb3e-eef9-47d0-869b-e5e4e0e34796 +title: Symfony Firewalls +--- + +- [Lazy Firewalls](20201113183038-lazy_firewalls) diff --git a/content/wiki/20201113183442-string_component.md b/content/wiki/20201113183442-string_component.md new file mode 100644 index 0000000..4cd940b --- /dev/null +++ b/content/wiki/20201113183442-string_component.md @@ -0,0 +1,84 @@ +--- +date: 2020-11-13 +id: 36b7429a-aeba-45bf-beaa-98add87e1504 +title: String Component +--- + +# Syntax + +## Working with strings + +``` php +use Symfony\Component\String\ByteString; +use Symfony\Component\String\CodePointString; +use Symfony\Component\String\UnicodeString; + +$content = new CodePointString('Hello world'); +$content = new UnicodeString('नमस्ते दुनिया'); +$content = new ByteString('さよなら'); + +$content = (new CodePointString('hello'))->toUnicodeString(); +$content = UnicodeString::fromCodePoints(0x68, 0x65, 0x6C, 0x6C, 0x6F)->toByteString(); +``` + +``` php +use function Symfony\Component\String\b; +use function Symfony\Component\String\u; + +// both are equivalent +$content = b('hello'); +$content = new ByteString('hello'); + +// both are equivalent +$content = u('hello'); +$content = new UnicodeString('hello'); +``` + +## Object-oriented strings + +``` php +// using PHP functions +if ('.html' === substr($theString, -strlen('.html'))) { + // ... +} + +// using Symfony's String +if (u($theString)->endsWith('.html')) { + // ... +} +``` + +``` php +$text =u('This is a déjà-vu situation.') + ->trimEnd('.') + ->replace('déjà-vu', 'jamais-vu') + ->append('!'); +// $text = 'This is a jamais-vu situation!' +``` + +``` php +u('FOO Bar')->folded(); // 'foo bar' +u('Die O\'Brian Straße')->folded(); // "die o'brian strasse" +``` + +## String Slugger + +``` php +use Symfony\Component\String\Slugger\AsciiSlugger; + +$slugger = new AsciiSlugger(); +$slugger->slug('Стойността трябва', '-', 'bg'); // 'Stoinostta-tryabva' +$slugger->slug('Αυτή η τιμή πρέπει', '-', 'el'); // 'Avti-i-timi-prepi' +$slugger->slug('该变量的值应为', '-', 'zh'); // 'gai-bian-liang-de-zhi-ying-wei' +$slugger->slug('Wôrķšƥáçè sèťtïñğš'); // 'Workspace-settings' +``` + +## Twig Integration + +``` twig +{{ 'Lorem ipsum'|u.truncate(8, '...') }} +{# prints: Lorem... #} + +{{ 'SymfonyStringWithTwig'|u.snake }} +{# prints: symfony_string_with_twig #} +``` diff --git a/content/wiki/20201113183442-symfony_string_component.md b/content/wiki/20201113183442-symfony_string_component.md new file mode 100644 index 0000000..e0b855a --- /dev/null +++ b/content/wiki/20201113183442-symfony_string_component.md @@ -0,0 +1,100 @@ +--- +date: 2020-11-13 +id: ec38d6f0-c958-478b-9701-99a535b9adc9 +title: Symfony String Component +--- + +# Interfaces + +- [Stringable Interface](20201116125716-stringable_interface) + +# Syntax + +- [containsAny()](20201116130503-containsany) +- [fromRandom()](20201116142317-fromrandom) +- [reverse()](20201116130738-reverse) +- [truncate()](20201116130210-truncate) + +## Misc + +### String conversion + +``` php +use Symfony\Component\String\ByteString; +use Symfony\Component\String\CodePointString; +use Symfony\Component\String\UnicodeString; + +$content = new CodePointString('Hello world'); +$content = new UnicodeString('नमस्ते दुनिया'); +$content = new ByteString('さよなら'); + +$content = (new CodePointString('hello'))->toUnicodeString(); +$content = UnicodeString::fromCodePoints(0x68, 0x65, 0x6C, 0x6C, 0x6F)->toByteString(); +``` + +``` php +use function Symfony\Component\String\b; +use function Symfony\Component\String\u; + +// both are equivalent +$content = b('hello'); +$content = new ByteString('hello'); + +// both are equivalent +$content = u('hello'); +$content = new UnicodeString('hello'); +``` + +### Object-oriented strings + +``` php +// using PHP functions +if ('.html' === substr($theString, -strlen('.html'))) { + // ... +} + +// using Symfony's String +if (u($theString)->endsWith('.html')) { + // ... +} +``` + +``` php +$text =u('This is a déjà-vu situation.') + ->trimEnd('.') + ->replace('déjà-vu', 'jamais-vu') + ->append('!'); +// $text = 'This is a jamais-vu situation!' +``` + +``` php +u('FOO Bar')->folded(); // 'foo bar' +u('Die O\'Brian Straße')->folded(); // "die o'brian strasse" +``` + +### String Slugger + +``` php +use Symfony\Component\String\Slugger\AsciiSlugger; + +$slugger = new AsciiSlugger(); +$slugger->slug('Стойността трябва', '-', 'bg'); // 'Stoinostta-tryabva' +$slugger->slug('Αυτή η τιμή πρέπει', '-', 'el'); // 'Avti-i-timi-prepi' +$slugger->slug('该变量的值应为', '-', 'zh'); // 'gai-bian-liang-de-zhi-ying-wei' +$slugger->slug('Wôrķšƥáçè sèťtïñğš'); // 'Workspace-settings' +``` + +### Twig Integration + +``` twig +{{ 'Lorem ipsum'|u.truncate(8, '...') }} +{# prints: Lorem... #} + +{{ 'SymfonyStringWithTwig'|u.snake }} +{# prints: symfony_string_with_twig #} +``` + +# Related + +- [Symfony Components](20201110152627-symfony_components) +- [Symfony 5.0](20201113172025-symfony_5_0) diff --git a/content/wiki/20201114101358-quotes.md b/content/wiki/20201114101358-quotes.md new file mode 100644 index 0000000..c562dd7 --- /dev/null +++ b/content/wiki/20201114101358-quotes.md @@ -0,0 +1,13 @@ +--- +date: 2020-11-14 +id: 28f38a51-7032-4ead-a13b-7022b5a55a8f +title: Quotes +--- + +# Eisenhower + +- [You can't have this kind of war. There aren't enough bulldozers to + scrape the bodies off the + streets.](20201114101614-you_can_t_have_this_kind_of_war_there_aren_t_enough_bulldozers_to_scrape_the_bodies_off_the_streets) + +# Pournelle diff --git a/content/wiki/20201114101614-you_can_t_have_this_kind_of_war_there_aren_t_enough_bulldozers_to_scrape_the_bodies_off_the_streets.md b/content/wiki/20201114101614-you_can_t_have_this_kind_of_war_there_aren_t_enough_bulldozers_to_scrape_the_bodies_off_the_streets.md new file mode 100644 index 0000000..33da048 --- /dev/null +++ b/content/wiki/20201114101614-you_can_t_have_this_kind_of_war_there_aren_t_enough_bulldozers_to_scrape_the_bodies_off_the_streets.md @@ -0,0 +1,10 @@ +--- +date: 2020-11-14 +id: 6e115d85-8c0c-48a5-87d8-5893684251b4 +title: You can't have this kind of war. There aren't enough bulldozers + to scrape the bodies off the streets. +--- + +> You just can't have this kind of war. There aren't enough bulldozers +> to scrape the bodies off the streets. —[Dwight D. +> Eisenhowfr](20201114102043-dwight_d_eisenhower) diff --git a/content/wiki/20201114101721-political_science.md b/content/wiki/20201114101721-political_science.md new file mode 100644 index 0000000..aff0933 --- /dev/null +++ b/content/wiki/20201114101721-political_science.md @@ -0,0 +1,8 @@ +--- +date: 2020-11-14 +id: 8faa9b85-f3e6-4f4d-9daf-b2892df3c6fe +title: Political Science +--- + +- [American Presidents](20201114101926-american_presidents) +- [Political science terms](20201029200040-political_science_terms) diff --git a/content/wiki/20201114101926-american_presidents.md b/content/wiki/20201114101926-american_presidents.md new file mode 100644 index 0000000..2d1be13 --- /dev/null +++ b/content/wiki/20201114101926-american_presidents.md @@ -0,0 +1,7 @@ +--- +date: 2020-11-14 +id: c54a96ac-cf9c-43d1-ab99-c646be37aac9 +title: American Presidents +--- + +- [Dwight D. Eisenhower](20201114102043-dwight_d_eisenhower) diff --git a/content/wiki/20201114102043-dwight_d_eisenhower.md b/content/wiki/20201114102043-dwight_d_eisenhower.md new file mode 100644 index 0000000..1ff62c8 --- /dev/null +++ b/content/wiki/20201114102043-dwight_d_eisenhower.md @@ -0,0 +1,13 @@ +--- +date: 2020-11-14 +id: 5a86f956-ff77-446d-9dc4-1246b098fd72 +title: Dwight D. Eisenhower +--- + +# Quotes + +## Nuclear War + +- [You can't have this kind of war. There aren't enough bulldozers to + scrape the bodies off the + streets.](20201114101614-you_can_t_have_this_kind_of_war_there_aren_t_enough_bulldozers_to_scrape_the_bodies_off_the_streets) diff --git a/content/wiki/20201114102140-nuclear_war.md b/content/wiki/20201114102140-nuclear_war.md new file mode 100644 index 0000000..102cd7b --- /dev/null +++ b/content/wiki/20201114102140-nuclear_war.md @@ -0,0 +1,11 @@ +--- +date: 2020-11-14 +id: 2f3eb1c2-669f-4c7f-ad03-19cfd76812ef +title: Nuclear War +--- + +# Quotes + +- [You can't have this kind of war. There aren't enough bulldozers to + scrape the bodies off the + streets.](20201114101614-you_can_t_have_this_kind_of_war_there_aren_t_enough_bulldozers_to_scrape_the_bodies_off_the_streets) diff --git a/content/wiki/20201115141421-conventional_changelog.md b/content/wiki/20201115141421-conventional_changelog.md new file mode 100644 index 0000000..4cb5a61 --- /dev/null +++ b/content/wiki/20201115141421-conventional_changelog.md @@ -0,0 +1,18 @@ +--- +date: 2020-11-15 +id: 1107e71e-4459-4ebc-85e4-f7bfde2c684a +title: Conventional changelog +--- + +- [Commit guidelines](20201115141620-commit_guidelines) + +# Reference + +- Spec[^1] +- commitlint[^2] + +# Footnotes + +[^1]: + +[^2]: diff --git a/content/wiki/20201115141620-commit_guidelines.md b/content/wiki/20201115141620-commit_guidelines.md new file mode 100644 index 0000000..201e3a4 --- /dev/null +++ b/content/wiki/20201115141620-commit_guidelines.md @@ -0,0 +1,60 @@ +--- +date: 2020-11-15 +id: e57b1687-eeb8-4d10-b152-015a9d8dcec4 +title: Commit guidelines +--- + +# Commit Message Format + + (): + + + +