Monty  Boehm

Monty Boehm

1668825314

How to Declare Global Variables in React Applications

Declare React global variable with code examples

Learn how to declare global variables in React applications.

There are two ways you can declare a global variable in a React application:

This tutorial will cover both ways mentioned above.

Attaching global variable to the window object

One way to declare a global variable in React is to attach a new variable as the property of the window object.

For example, create a window.name variable in the index.js file like this:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

window.name = "John";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Once the variable is declared, you can call it from another React component you have in your project.

Here’s an example of calling the variable from the App.js file:

import React from "react";

export default function App() {
  return <h1>Hello {window.name}</h1>;
}

The window object can be created anywhere inside your code (it doesn’t have to be in the parent component)

In the code below, the global variable is declared inside the App.js file:

import React from "react";

window.user = "Nathan";

export default function App() {
  return <h1>Hello World!</h1>;
}

The user variable can still be called from the index.js file as shown below:

root.render(
  <React.StrictMode>
    <App />
    <p>Logged in as {window.user}</p>
  </React.StrictMode>
);

Although it’s not required, you can prefix the variable name with the dollar sign ($) to identify it as a global variable.

The $ will differentiate a global variable from a regular one:

window.$name = "John";

Add the $ when calling it from other components:

export default function App() {
  return <h1>Hello {window.$name}</h1>;
}

And that’s how you declare a global variable using the window object.

Using an env file to declare global variables

When you bootstrap your application using Create React App or Next.js, your application will automatically load a .env file that you created in the root directory.

You can create the .env file and declare a global variable there. It will be accessible from all the components you have in your application.

First, create a file named .env in your root directory:

touch .env

Then declare a global variable in the env file. The convention in .env file is to use all uppercase letters for the variable name:

REACT_APP_NAME_VARIABLE = John

To call on the environment variable, use the process.env.{ your variable name } syntax as follows:

export default function App() {
  return (
    <div className="App">
      <h1>Hello {process.env.REACT_APP_NAME_VARIABLE}</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

For further information, you can look at the documentation of Create React App or Next.js.

Unlike state and props, the global variables you declared inside the window or process.env object won’t be tracked for change.

This means React will not update the UI when you change them. They are good for variables that have constant value and never change through the lifetime of your application.

If you want global variables that get tracked by React and update your UI according to its changes, then you need to use React Context API instead.

And that’s it for declaring a React global variable. Thanks for reading! 🙏

Original article source at: https://sebhastian.com/

#react #global #variables 

How to Declare Global Variables in React Applications

EAGO.jl: Easy-Advanced Global Optimization

EAGO: Easy-Advanced Global Optimization

EAGO is an open-source development environment for robust and global optimization in Julia.

EAGO's Optimizer Capabilities

EAGO is a deterministic global optimizer designed to address a wide variety of optimization problems, emphasizing nonlinear programs (NLPs), by propagating McCormick relaxations along the factorable structure of each expression in the NLP. Most operators supported by modern automatic differentiation (AD) packages (e.g. +, sin, cosh) are supported by EAGO and a number utilities for sanitizing native Julia code and generating relaxations on a wide variety of user-defined functions have been included. Currently, EAGO supports problems that have a priori variable bounds defined and have differentiable constraints. That is, problems should be specified in the generic form below:

EAGO's Relaxations

For each nonlinear term, EAGO makes use of factorable representations to construct bounds and relaxations. In the case of F = y(y-5)sin(y), a list is generated and rules for constructing McCormick relaxations are used to formulate relaxations in the original Y decision space1:

  • v1 = y
  • v2 = v1 - 5
  • v3 = sin(v1)
  • v4 = v1v2
  • v5 = v4v3
  • F = v5

Either these original relaxations, differentiable McCormick relaxations2, or affine relaxations thereof can be used to construct relaxations of optimization problems useful in branch and bound routines for global optimization. Utilities are included to combine these with algorithms for relaxing implicit functions3 and forward-reverse propagation of McCormick arithmetic4.

Sample Usage

EAGO makes use of the JuMP algebraic modeling language to improve the user's experience in setting up optimization models. Consider the familiar "process" problem instance5:

This model can be formulated using JuMP code as:

using JuMP, EAGO

m = Model(EAGO.Optimizer)

# Define bounded variables
xL = [10.0; 0.0; 0.0; 0.0; 0.0; 85.0; 90.0; 3.0; 1.2; 145.0]
xU = [2000.0; 16000.0; 120.0; 5000.0; 2000.0; 93.0; 95.0; 12.0; 4.0; 162.0]
@variable(m, xL[i] <= x[i=1:10] <= xU[i])

# Define nonlinear constraints
@NLconstraint(m, e1, -x[1]*(1.12+0.13167*x[8]-0.00667* (x[8])^2)+x[4] == 0.0)
@NLconstraint(m, e3, -0.001*x[4]*x[9]*x[6]/(98-x[6])+x[3] == 0.0)
@NLconstraint(m, e4, -(1.098*x[8]-0.038* (x[8])^2)-0.325*x[6]+x[7] == 57.425)
@NLconstraint(m, e5, -(x[2]+x[5])/x[1]+x[8] == 0.0)

# Define linear constraints
@constraint(m, e2, -x[1]+1.22*x[4]-x[5] == 0.0)
@constraint(m, e6, x[9]+0.222*x[10] == 35.82)
@constraint(m, e7, -3*x[7]+x[10] == -133.0)

# Define nonlinear objective
@NLobjective(m, Max, 0.063*x[4]*x[7] - 5.04*x[1] - 0.035*x[2] - 10*x[3] - 3.36*x[5])

# Solve the optimization problem
JuMP.optimize!(m)

Special handling has been included for linear/quadratic functions defined using the @constraint macro in JuMP and these can generally be expected to perform better than specifying quadratic or linear terms with the @NLconstraint macro.

A Cautionary Note on Global Optimization

As a global optimization platform, EAGO's solvers can be used to find solutions of general nonconvex problems with a guaranteed certificate of optimality. However, global solvers suffer from the curse of dimensionality and therefore their performance is outstripped by convex/local solvers. For users interested in large-scale applications, be warned that problems generally larger than a few variables may prove challenging for certain types of global optimization problems.

Package Capabilities

The EAGO package has numerous features: a solver accessible from JuMP/MathOptInterface, domain reduction routines, McCormick relaxations, and specialized non-convex semi-infinite program solvers. A full description of all EAGO features is available in the documentation website. A series of example have been provided in the form of Jupyter notebooks in the separate EAGO-notebooks repository.

Recent News

  • 2/5/2021: EAGO v0.6.0 has been tagged.
    • License changed from CC BY-NC-SA 4.0 to MIT
    • Fix deprecated Ipopt constructor
    • Fix discrepancy between the returned objective value and the objective evaluated at the solution.
    • Dramatically decrease allocates and first-run performance of SIP routines.
    • Add two algorithms which modify SIPres detailed in Djelassi, H. and Mitsos A. 2017.
    • Fix objective interval fallback function.
    • New SIP interface with extendable subroutines.
    • Fix x^y relaxation bug.
    • Add issues template.
    • Add SIP subroutine documentation.

For a full list of EAGO release news, see click here

Installing EAGO

EAGO is a registered Julia package and it can be installed using the Julia package manager. From the Julia REPL, type ] to enter the Pkg REPL mode and run the following command

pkg> add EAGO

Currently, EAGO is tied to a 0.19+ or greater version of JuMP. This allows a replication of some of the internal features shared by EAGO and JuMP's AD scheme aka generation of Wengert Tapes pass evaluators between JuMP and EAGO etc.

pkg> add JuMP

EAGO v0.6.0 is the current tagged version and requires Julia 1.2+ for full functionality (however Julia 1.0+ versions support partial functionality). Use with version 1.5 is recommended as the majority of in-house testing has occurred using this version of Julia. The user is directed to the High-Performance Configuration for instructions on how to install a high performance version of EAGO (rather than the basic entirely open-source version). If any issues are encountered when loading EAGO (or when using it), please submit an issue using the Github issue tracker.

Bug reporting, support and feature requests

Please report bugs or feature requests by opening an issue using the Github issue tracker. All manners of feedback are encouraged.

Current limitations

  • Nonlinear handling assumes that box-constraints of nonlinear terms are available or can be inferred from bounds-tightening.
  • Only currently supports continuous functions. Support for mixed-integer problems is forthcoming.

Work In Progress

  • Extensions for nonconvex dynamic global & robust optimization.
  • Provide support for mixed-integer problems.
  • Update EAGO to support nonsmooth problems (requires: a nonsmooth local nlp optimizer or lexiographic AD, support for relaxations is already included).
  • Performance assessment of nonlinear (differentiable) relaxations and incorporation into main EAGO routine.
  • Evaluation and incorporation of implicit relaxation routines in basic solver.

Citing EAGO

Please cite the following paper when using EAGO. In plain text form this is:

 M. E. Wilhelm & M. D. Stuber (2020) EAGO.jl: easy advanced global optimization in Julia,
 Optimization Methods and Software, DOI: 10.1080/10556788.2020.1786566

A corresponding bibtex entry text is given below and a corresponding .bib file is given in citation.bib.

@article{doi:10.1080/10556788.2020.1786566,
author = { M. E.   Wilhelm  and  M. D.   Stuber },
title = {EAGO.jl: easy advanced global optimization in Julia},
journal = {Optimization Methods and Software},
pages = {1-26},
year  = {2020},
publisher = {Taylor & Francis},
doi = {10.1080/10556788.2020.1786566},
URL = {https://doi.org/10.1080/10556788.2020.1786566},
eprint = {https://doi.org/10.1080/10556788.2020.1786566}
}

Related Packages

  • ValidatedNumerics.jl:A Julia library for validated interval calculations, including basic interval extensions, constraint programming, and interval contactors
  • MAiNGO: An open-source mixed-integer nonlinear programming package in C++ that utilizes MC++ for relaxations.
  • MC++: A mature McCormick relaxation package in C++ that also includes McCormick-Taylor, Chebyshev Polyhedral and Ellipsoidal arithmetics.

References

  1. A. Mitsos, B. Chachuat, and P. I. Barton. McCormick-based relaxations of algorithms. SIAM Journal on Optimization, 20(2):573–601, 2009.
  2. K.A. Khan, HAJ Watson, P.I. Barton. Differentiable McCormick relaxations. Journal of Global Optimization, 67(4):687-729 (2017).
  3. Stuber, M.D., Scott, J.K., Barton, P.I.: Convex and concave relaxations of implicit functions. Optim. Methods Softw. 30(3), 424–460 (2015)
  4. A., Wechsung JK Scott, HAJ Watson, and PI Barton. Reverse propagation of McCormick relaxations. Journal of Global Optimization 63(1):1-36 (2015).
  5. Bracken, Jerome and McCormick, Garth P. Selected Applications of Nonlinear Programming, John Wiley and Sons, New York, 1968.

Download Details:

Author: PSORLab
Source Code: https://github.com/PSORLab/EAGO.jl 
License: View license

#julia #optimization #global 

EAGO.jl: Easy-Advanced Global Optimization
Nat  Grady

Nat Grady

1660948560

RStudio Addin to Remove Objects From The Global Environment

objectremover  

objectremover is an RStudio addin to assist with clearing objects from the Global environment. Features include removing objects by

  • Starting pattern of object name
  • Ending pattern of object name
  • Regular expression
  • Object type (dataframe, function and other)

The addin allows the user to quickly tidy up the R workspace which is useful, e.g. when you have stored lots of large, temporary objects in memory which can often happen during the course of exploratory data analysis. objectremover displays exactly which objects will be removed according to the options the user has specified in real time. This feature helps to ensure that you do not remove certain objects by mistake.

Installation

Install objectremover from CRAN with

install.packages("objectremover")

Alternatively, you can install the development version of objectremover with

remotes::install_github("alan-y/objectremover", ref = "main")

Use

After installing the package, the add-in will be available in RStudio from the Addins dropdown menu. Select “Remove Objects” (under the heading OBJECTREMOVER) from the menu to run.

If, for example, you have created some temporary objects named using the prefix ‘z’, objectremover can be used to quickly remove all objects starting with ‘z’ from the Global environment.

objectremover demo

Download Details:

Author: Alan-y
Source Code: https://github.com/alan-y/objectremover 
License: Unknown, MIT licenses found

#r #rstudio #global #environment 

RStudio Addin to Remove Objects From The Global Environment
Monty  Boehm

Monty Boehm

1659547620

SCIP.jl: Julia interface to SCIP Solver

SCIP.jl

Julia interface to the SCIP solver. 

See NEWS.md for changes in each (recent) release.

Update (April 2022)

Due to breaking changes, only SCIP 8 is supported by the wrapper on version 0.11 onwards.

Update (August 2020)

On MacOS and Linux, it is no longer required to install the SCIP binaries using this package. There now exists a BinaryBuilder.jl generated package SCIP_jll.jl and SCIP_PaPILO_jll.jl which is installed automatically as a dependency.

On Windows, the separate installation of SCIP is still mandatory, otherwise, you can use this default installation:

pkg> add SCIP

If you use an older Julia version, Windows or want a custom SCIP installation, see below for the build steps.

Custom SCIP installations.

If you prefer to link to your own installation of SCIP, please set the environment variable SCIPOPTDIR to point to the installation path. That is, either $SCIPOPTDIR/lib/libscip.so, $SCIPOPTDIR/lib/libscip.dylib or $SCIPOPTDIR/bin/scip.dll should exist, depending on your operating system.

When this is set before you install this package, it should be recognized automatically. Afterwards, you can trigger the build with

pkg> build SCIP

Setting Parameters

There are two ways of setting the parameters (all are supported). First, using MOI.set:

using MOI
using SCIP

optimizer = SCIP.Optimizer()
MOI.set(optimizer, MOI.RawOptimizerAttribute("display/verblevel"), 0)
MOI.set(optimizer, MOI.RawOptimizerAttribute("limits/gap"), 0.05)

Second, as keyword arguments to the constructor. But here, the slashes (/) need to be replaced by underscores (_) in order to end up with a valid Julia identifier. This should not lead to ambiguities as none of the official SCIP parameters contain any underscores (yet).

using MOI
using SCIP

optimizer = SCIP.Optimizer(display_verblevel=0, limits_gap=0.05)

Note that in both cases, the correct value type must be used (here, Int64 and Float64).

Design Considerations

Wrapper of Public API: All of SCIP's public API methods are wrapped and available within the SCIP package. This includes the scip_*.h and pub_*.h headers that are collected in scip.h, as well as all default constraint handlers (cons_*.h.) But the wrapped functions do not transform any data structures and work on the raw pointers (e.g. SCIP* in C, Ptr{SCIP_} in Julia). Convenience wrapper functions based on Julia types are added as needed.

Memory Management: Programming with SCIP requires dealing with variable and constraints objects that use reference counting for memory management. The SCIP.Optimizer wrapper type collects lists of SCIP_VAR* and SCIP_CONS* under the hood, and releases all reference when it is garbage collected itself (via finalize). When adding a variable (add_variable) or a constraint (add_linear_constraint), an integer index is returned. This index can be used to retrieve the SCIP_VAR* or SCIP_CONS* pointer via get_var and get_cons respectively.

Supported Features for MathOptInterface: We aim at exposing many of SCIP's features through MathOptInterface. However, the focus is on keeping the wrapper simple and avoiding duplicate storage of model data.

As a consequence, we do not currently support some features such as retrieving constraints by name (VariableIndex-set constraints are not stored as SCIP constraints explicitly).

Support for more constraint types (quadratic, SOS1/2, nonlinear expression) is implemented, but SCIP itself only supports affine objective functions, so we will stick with that. More general objective functions could be implented via a bridge.

Supported operators in nonlinear expressions are as follows:

  • unary: -, sqrt, exp, log, abs, cos, sin
  • binary: -, /, ^
  • n-ary: +, *

Author: Scipopt
Source Code: https://github.com/scipopt/SCIP.jl 
License: MIT license

#julia #global 

SCIP.jl: Julia interface to SCIP Solver
Brook  Hudson

Brook Hudson

1659210780

Commander: The Complete Solution for Ruby Command-line Executables

 Commander

The complete solution for Ruby command-line executables. Commander bridges the gap between other terminal related libraries you know and love (OptionParser, HighLine), while providing many new features, and an elegant API.

Features

  • Easier than baking cookies
  • Parses options using OptionParser
  • Auto-populates struct with options ( no more { |v| options[:recursive] = v } )
  • Auto-generates help documentation via pluggable help formatters
  • Optional default command when none is present
  • Global / Command level options
  • Packaged with two help formatters (Terminal, TerminalCompact)
  • Imports the highline gem for interacting with the terminal
  • Adds additional user interaction functionality
  • Highly customizable progress bar with intuitive, simple usage
  • Multi-word command name support such as drupal module install MOD, rather than drupal module_install MOD
  • Sexy paging for long bodies of text
  • Support for MacOS text-to-speech
  • Command aliasing (very powerful, as both switches and arguments can be used)
  • Growl notification support for MacOS
  • Use the commander executable to initialize a commander driven program

Installation

$ gem install commander

Quick Start

To generate a quick template for a commander app, run:

$ commander init yourfile.rb

To generate a quick modular style template for a commander app, run:

$ commander init --modular yourfile.rb

Example

For more option examples view the Commander::Command#option method. Also an important feature to note is that action may be a class to instantiate, as well as an object, specifying a method to call, so view the RDoc for more information.

Classic style

require 'rubygems'
require 'commander/import'

# :name is optional, otherwise uses the basename of this executable
program :name, 'Foo Bar'
program :version, '1.0.0'
program :description, 'Stupid command that prints foo or bar.'

command :foo do |c|
  c.syntax = 'foobar foo'
  c.description = 'Displays foo'
  c.action do |args, options|
    say 'foo'
  end
end

command :bar do |c|
  c.syntax = 'foobar bar [options]'
  c.description = 'Display bar with optional prefix and suffix'
  c.option '--prefix STRING', String, 'Adds a prefix to bar'
  c.option '--suffix STRING', String, 'Adds a suffix to bar'
  c.action do |args, options|
    options.default :prefix => '(', :suffix => ')'
    say "#{options.prefix}bar#{options.suffix}"
  end
end

Example output:

$ foobar bar
# => (bar)

$ foobar bar --suffix '}' --prefix '{'
# => {bar}

Modular style

NOTE: Make sure to use require 'commander' rather than require 'commander/import', otherwise Commander methods will still be imported into the global namespace.

require 'rubygems'
require 'commander'

class MyApplication
  include Commander::Methods

  def run
    program :name, 'Foo Bar'
    program :version, '1.0.0'
    program :description, 'Stupid command that prints foo or bar.'

    command :foo do |c|
      c.syntax = 'foobar foo'
      c.description = 'Displays foo'
      c.action do |args, options|
        say 'foo'
      end
    end

    run!
  end
end

MyApplication.new.run if $0 == __FILE__

Block style

require 'rubygems'
require 'commander'

Commander.configure do
  program :name, 'Foo Bar'
  program :version, '1.0.0'
  program :description, 'Stupid command that prints foo or bar.'

  # see classic style example for options
end

HighLine

As mentioned above, the highline gem is imported into the global scope. Here are some quick examples for how to utilize highline in your commands:

# Ask for password masked with '*' character
ask("Password:  ") { |q| q.echo = "*" }

# Ask for password
ask("Password:  ") { |q| q.echo = false }

# Ask if the user agrees (yes or no)
agree("Do something?")

# Asks on a single line (note the space after ':')
ask("Name: ")

# Asks with new line after "Description:"
ask("Description:")

# Calls Date#parse to parse the date string passed
ask("Birthday? ", Date)

# Ensures Integer is within the range specified
ask("Age? ", Integer) { |q| q.in = 0..105 }

# Asks for a list of strings, converts to array
ask("Fav colors?", Array)

HighLine & Interaction Additions

In addition to highline's fantastic choice of methods, commander adds the following methods to simplify common tasks:

# Ask for password
password

# Ask for password with specific message and mask character
password "Enter your password please:", '-'

# Ask for CLASS, which may be any valid class responding to #parse. Date, Time, Array, etc
names = ask_for_array 'Names: '
bday = ask_for_date 'Birthday?: '

# Simple progress bar (Commander::UI::ProgressBar)
uris = %w[
  http://vision-media.ca
  http://google.com
  http://yahoo.com
]
progress uris do |uri|
  res = open uri
  # Do something with response
end

# 'Log' action to stdout
log "create", "path/to/file.rb"

# Enable paging of output after this point
enable_paging

# Ask editor for input (EDITOR environment variable or whichever is available: TextMate, vim, vi, emacs, nano, pico)
ask_editor

# Ask editor, supplying initial text
ask_editor 'previous data to update'

# Ask editor, preferring a specific editor
ask_editor 'previous data', 'vim'

# Choose from an array of elements
choice = choose("Favorite language?", :ruby, :perl, :js)

# Alter IO for the duration of the block
io new_input, new_output do
  new_input_contents = $stdin.read
  puts new_input_contents # outputs to new_output stream
end
# $stdin / $stdout reset back to original streams

# Speech synthesis
speak 'What is your favorite food? '
food = ask 'favorite food?: '
speak "Wow, I like #{food} too. We have so much in common."
speak "I like #{food} as well!", "Victoria", 190

# Execute arbitrary applescript
applescript 'foo'

# Converse with speech recognition server
case converse 'What is the best food?', :cookies => 'Cookies', :unknown => 'Nothing'
when :cookies
  speak 'o.m.g. you are awesome!'
else
  case converse 'That is lame, shall I convince you cookies are the best?', :yes => 'Ok', :no => 'No', :maybe => 'Maybe another time'
  when :yes
    speak 'Well you see, cookies are just fantastic, they melt in your mouth.'
  else
    speak 'Ok then, bye.'
  end
end

Growl Notifications

Commander provides methods for displaying Growl notifications. To use these methods you need to install https://github.com/tj/growl which utilizes the growlnotify executable. Note that growl is auto-imported by Commander when available, no need to require.

# Display a generic Growl notification
notify 'Something happened'

# Display an 'info' status notification
notify_info 'You have #{emails.length} new email(s)'

# Display an 'ok' status notification
notify_ok 'Gems updated'

# Display a 'warning' status notification
notify_warning '1 gem failed installation'

# Display an 'error' status notification
notify_error "Gem #{name} failed"

Commander Goodies

Option Defaults

The options struct passed to #action provides a #default method, allowing you to set defaults in a clean manner for options which have not been set.

command :foo do |c|
  c.option '--interval SECONDS', Integer, 'Interval in seconds'
  c.option '--timeout SECONDS', Integer, 'Timeout in seconds'
  c.action do |args, options|
    options.default \
      :interval => 2,
      :timeout  => 60
  end
end

Command Aliasing

Aliases can be created using the #alias_command method like below:

command :'install gem' do |c|
  c.action { puts 'foo' }
end
alias_command :'gem install', :'install gem'

Or more complicated aliases can be made, passing any arguments as if it was invoked via the command line:

command :'install gem' do |c|
  c.syntax = 'install gem <name> [options]'
  c.option '--dest DIR', String, 'Destination directory'
  c.action { |args, options| puts "installing #{args.first} to #{options.dest}" }
end
alias_command :update, :'install gem', 'rubygems', '--dest', 'some_path'
$ foo update
# => installing rubygems to some_path

Command Defaults

Although working with a command executable framework provides many benefits over a single command implementation, sometimes you still want the ability to create a terse syntax for your command. With that in mind we may use #default_command to help with this. Considering our previous :'install gem' example:

default_command :update
$ foo
# => installing rubygems to some_path

Keeping in mind that commander searches for the longest possible match when considering a command, so if you were to pass arguments to foo like below, expecting them to be passed to :update, this would be incorrect, and would end up calling :'install gem', so be careful that the users do not need to use command names within the arguments.

$ foo install gem
# => installing  to

Long descriptions

If you need to have a long command description, keep your short description under summary, and consider multi-line strings for description:

  program :summary, 'Stupid command that prints foo or bar.'
  program :description, %q(
#{c.summary}

More information about that stupid command that prints foo or bar.

And more
  )

Additional Global Help

Arbitrary help can be added using the following #program symbol:

program :help, 'Author', 'TJ Holowaychuk <tj@vision-media.ca>'

Which will output the rest of the help doc, along with:

AUTHOR:

  TJ Holowaychuk <tj@vision-media.ca>

Global Options

Although most switches will be at the command level, several are available by default at the global level, such as --version, and --help. Using #global_option you can add additional global options:

global_option('-c', '--config FILE', 'Load config data for your commands to use') { |file| ... }

This method accepts the same syntax as Commander::Command#option so check it out for documentation.

All global options regardless of providing a block are accessable at the command level. This means that instead of the following:

global_option('--verbose') { $verbose = true }
...
c.action do |args, options|
  say 'foo' if $verbose
...

You may:

global_option '--verbose'
...
c.action do |args, options|
  say 'foo' if options.verbose
...

Formatters

Two core formatters are currently available, the default Terminal formatter as well as TerminalCompact. To utilize a different formatter simply use :help_formatter like below:

program :help_formatter, Commander::HelpFormatter::TerminalCompact

Or utilize the help formatter aliases:

program :help_formatter, :compact

This abstraction could be utilized to generate HTML documentation for your executable.

Tracing

By default the -t and --trace global options are provided to allow users to get a backtrace to aid debugging.

You can disable these options:

never_trace!

Or make it always on:

always_trace!

Tips

When adding a global or command option, OptionParser implicitly adds a small switch even when not explicitly created, for example -c will be the same as --config in both examples, however -c will only appear in the documentation when explicitly assigning it.

global_option '-c', '--config FILE'
global_option '--config FILE'

ASCII Tables

For feature rich ASCII tables for your terminal app check out the terminal-table gem at https://github.com/tj/terminal-table

+----------+-------+----+--------+-----------------------+
| Terminal | Table | Is | Wicked | Awesome               |
+----------+-------+----+--------+-----------------------+
|          |       |    |        | get it while its hot! |
+----------+-------+----+--------+-----------------------+

Running Specifications

$ rake spec

OR

$ spec --color spec

Contrib

Feel free to fork and request a pull, or submit a ticket https://github.com/commander-rb/commander/issues

License

This project is available under the MIT license. See LICENSE for details.


Author: commander-rb
Source code: https://github.com/commander-rb/commander
License: MIT license

#ruby  #ruby-on-rails 

Commander: The Complete Solution for Ruby Command-line Executables

Implementar La Globalización Y La Localización En .NET 6

¿Qué es la globalización y la localización?

La globalización y la localización es una técnica para diseñar la arquitectura de nuestra aplicación de manera que no esté vinculada a ningún idioma específico y en cualquier momento tengamos la capacidad de introducir más idiomas sin ningún tipo de reelaboración. Diseñamos nuestra aplicación para que sea neutral en cuanto al idioma. Para ser más precisos, cuando globalizamos nuestra aplicación no estamos codificando los valores de salida como cadenas sin procesar, sino que usamos una clave para identificar textos. Podemos identificar cualquier cosa como un texto clave o comprensible que podamos utilizar en la fase de localización. La localización significa que agregamos soporte para diferentes idiomas además de las aplicaciones globalizadas. Sin globalización no podemos localizar las aplicaciones. Puede haber excepciones en ocasiones en las que alguna acción no se puede traducir a otros idiomas que se pueden ignorar. También,  

La mejor manera de implementar este proceso se muestra arriba.

  1. Obtenga el contenido traducido.
  2. Globalice los valores codificados en claves.
  3. Cree los archivos de recursos y agregue contenido traducido.

globalización

Para implementar la globalización, convertiremos cada texto de nuestra aplicación en una clave, por ejemplo. Este valor estará disponible mediante el localizador IStringLocalizer<T> como inyección de dependencia, aquí T representará el nombre de nuestro componente Razor para el que estamos creando recursos. La clave y el valor residirán en nuestro archivo .resx y el fragmento de código en nuestro componente razor.

ValorLlaveFragmento de código
Hola Mundosaludo_holalocalizador['saludar_hola']
Sobre nosotrostítulo_acerca delocalizador['title_about']

Por ejemplo, a continuación se inyecta IStringLocalizer<NavMenu> Localizer como dependencia y estamos haciendo referencia a nombres clave para obtener valor.

Localización

Para implementar la localización, instalaremos el paquete de localización de extensiones de Microsoft.

<ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.5" />
</ItemGroup>

En nuestro Program.cs agregaremos middleware,

builder.Services.AddLocalization();

Ahora, crearemos un archivo de recursos para combinaciones de idioma y componentes. Tenemos que seguir la convención <ComponentName>.<language>.resx

Estructura del proyecto

Archivo de recursos NavMenu.fr-CA-resx

Ahora, elegiremos un idioma según las preferencias de los usuarios. Para implementar esto, almacenaremos el idioma seleccionado por el usuario en el navegador en almacenamiento local. A continuación se muestra un componente simple como referencia.

LanguageSelector.razor

<ul>
@foreach(var lang in new string[] { "en-IN","hi","pa","fr-CA" })
{
    <li><a href="#" onclick="(localStorage.setItem('lang','@lang'),window.location.reload())();">@lang</a></li>
}
</ul>

Para elegir el idioma del almacenamiento local y usarlo en la aplicación, nuestro código final se verá así.

índice.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>BlazorGlobalizationTutorial</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link href="BlazorGlobalizationTutorial.Client.styles.css" rel="stylesheet" />
<script>
//Function to get localizer language for webassembly C# code
    window.getCultureLang = () => {
        return window.localStorage['lang']
    };
</script>
</head>

<body>
    <div id="app">Loading...</div>
    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    <script>
//Function to get localizer language for application startup. If language is not set use ‘en-IN’
        let languageSet = (localStorage.getItem('lang') || 'en-IN');
        console.log(languageSet);
        Blazor.start({
            applicationCulture: languageSet
        });
    </script>
</body>
</html>

 Programa.cs

using BlazorGlobalizationTutorial.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using System.Globalization;
using Microsoft.JSInterop;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add < App > ("#app");
builder.RootComponents.Add < HeadOutlet > ("head::after");
builder.Services.AddScoped(sp => new HttpClient {
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
builder.Services.AddLocalization(); //Localizer added
var host = builder.Build();
/*Localizer setting start*/
var js = host.Services.GetRequiredService < IJSRuntime > ();
var lang = await js.InvokeAsync < string > ("getCultureLang");
CultureInfo.DefaultThreadCurrentCulture = string.IsNullOrWhiteSpace(lang) ? CultureInfo.CurrentCulture : new CultureInfo(lang);
CultureInfo.DefaultThreadCurrentUICulture = string.IsNullOrWhiteSpace(lang) ? CultureInfo.CurrentCulture : new CultureInfo(lang);
/*Localizer setting end*/
await host.RunAsync();

Para referencia, verifique el código cargado. Gracias por leer. 

Esta historia se publicó originalmente en https://www.c-sharpcorner.com/article/implement-globalization-and-localization-in-net-6-and-blazor-webassemly-app2/

#global #localization #dotnet #blazor 

Implementar La Globalización Y La Localización En .NET 6
坂本  健一

坂本 健一

1654256160

.NET6でグローバリゼーションとローカリゼーションを実装する

グローバリゼーションとローカリゼーションとは何ですか?

グローバリゼーションとローカリゼーションは、特定の言語に縛られないようにアプリケーションアーキテクチャを設計する手法であり、いつでも手直しなしでより多くの言語を導入することができます。アプリケーションは言語に依存しないように設計されています。より正確に言うと、アプリケーションをグローバル化する場合、出力値を生の文字列としてハードコーディングするのではなく、キーを使用してテキストを識別します。ローカリゼーションの段階で使用できる重要なテキストまたは理解しやすいテキストとして、あらゆるものを識別できます。ローカリゼーションとは、グローバル化されたアプリケーションに加えて、さまざまな言語のサポートを追加することを意味します。グローバリゼーションがなければ、アプリケーションをローカライズすることはできません。一部のアクションを無視できる他の言語に変換できない場合は、例外が発生する可能性があります。また、  

このプロセスを展開するための最良の方法は上に示されています。

  1. 翻訳されたコンテンツを取得します。
  2. ハードコードされた値をキーにグローバル化します。
  3. リソースファイルを作成し、翻訳されたコンテンツを追加します。

グローバリゼーション

グローバリゼーションを実装するために、たとえば、アプリケーションの各テキストをキーに変換します。この値は、依存性注入としてIStringLocalizer <T>ローカライザーを使用して利用できます。ここで、Tは、リソースを作成するRazorコンポーネント名を表します。キーと値は、razorコンポーネントの.resxファイルとコードスニペットにあります。

価値コードスニペット
こんにちは世界greet_helloローカライザー['greet_hello']
私たちに関してはtitle_aboutローカライザー['title_about']

たとえば、以下はIStringLocalizer <NavMenu>です。ローカライザーは依存関係として挿入され、値を取得するためにキー名を参照しています。

ローカリゼーション

ローカリゼーションを実装するには、MicrosoftExtensionLocalizationパッケージをインストールします。

<ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.5" />
</ItemGroup>

Program.csに、ミドルウェアを追加します。

builder.Services.AddLocalization();

次に、言語とコンポーネントの組み合わせ用のリソースファイルを作成します。規則<ComponentName>。<language>.resxに従う必要があります

プロジェクト構造

リソースファイルNavMenu.fr-CA-resx

次に、ユーザーの好みに基づいて言語を選択します。これを実装するために、ユーザーが選択した言語をブラウザのlocalstorageに保存します。以下は、参照用の簡単なコンポーネントです。

LanguageSelector.razor

<ul>
@foreach(var lang in new string[] { "en-IN","hi","pa","fr-CA" })
{
    <li><a href="#" onclick="(localStorage.setItem('lang','@lang'),window.location.reload())();">@lang</a></li>
}
</ul>

ローカルストレージから言語を選択してアプリケーションで使用するには、最終的なコードは次のようになります。

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>BlazorGlobalizationTutorial</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link href="BlazorGlobalizationTutorial.Client.styles.css" rel="stylesheet" />
<script>
//Function to get localizer language for webassembly C# code
    window.getCultureLang = () => {
        return window.localStorage['lang']
    };
</script>
</head>

<body>
    <div id="app">Loading...</div>
    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    <script>
//Function to get localizer language for application startup. If language is not set use ‘en-IN’
        let languageSet = (localStorage.getItem('lang') || 'en-IN');
        console.log(languageSet);
        Blazor.start({
            applicationCulture: languageSet
        });
    </script>
</body>
</html>

 Program.cs

using BlazorGlobalizationTutorial.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using System.Globalization;
using Microsoft.JSInterop;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add < App > ("#app");
builder.RootComponents.Add < HeadOutlet > ("head::after");
builder.Services.AddScoped(sp => new HttpClient {
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
builder.Services.AddLocalization(); //Localizer added
var host = builder.Build();
/*Localizer setting start*/
var js = host.Services.GetRequiredService < IJSRuntime > ();
var lang = await js.InvokeAsync < string > ("getCultureLang");
CultureInfo.DefaultThreadCurrentCulture = string.IsNullOrWhiteSpace(lang) ? CultureInfo.CurrentCulture : new CultureInfo(lang);
CultureInfo.DefaultThreadCurrentUICulture = string.IsNullOrWhiteSpace(lang) ? CultureInfo.CurrentCulture : new CultureInfo(lang);
/*Localizer setting end*/
await host.RunAsync();

参考までに、アップロードされたコードを確認してください。読んでくれてありがとう。 

このストーリーは、もともとhttps://www.c-sharpcorner.com/article/implement-globalization-and-localization-in-net-6-and-blazor-webassemly-app2/で公開されました。

#global #localization #dotnet #blazor 

.NET6でグローバリゼーションとローカリゼーションを実装する
坂本  篤司

坂本 篤司

1652450700

Pythonグローバル変数–グローバル変数の例を定義する方法

この記事では、グローバル変数の基本を学びます。

まず、Pythonで変数を宣言する方法と、「変数スコープ」という用語が実際に何を意味するかを学習します。

次に、ローカル変数とグローバル変数の違いを学び、グローバル変数の定義方法とglobalキーワードの使用方法を理解します。

Pythonの変数とは何ですか?どのように作成しますか?初心者のための紹介

変数はストレージコンテナと考えることができます。

これらは、コンピュータのメモリに保存したいデータ、情報、および値を保持するためのストレージコンテナです。その後、プログラムの存続期間中のある時点でそれらを参照したり、操作したりすることもできます。

変数にはシンボリックがあり、その名前は、その識別子として機能するストレージコンテナのラベルと考えることができます。

変数名は、その中に格納されているデータへの参照とポインターになります。したがって、データと情報の詳細を覚えておく必要はありません。そのデータと情報を保持する変数名を参照するだけで済みます。

変数に名前を付けるときは、変数が保持するデータを説明していることを確認してください。変数名は、将来の自分自身と一緒に作業する可能性のある他の開発者の両方にとって、明確で簡単に理解できる必要があります。

それでは、Pythonで実際に変数を作成する方法を見てみましょう。

Pythonで変数を宣言するときは、データ型を指定する必要はありません。

たとえば、Cプログラミング言語では、変数が保持するデータの型を明示的に指定する必要があります。

したがって、整数またはint型である年齢を格納したい場合、これはCで行う必要があることです。

#include <stdio.h>
 
int main(void)
{
  int age = 28;
  // 'int' is the data type
  // 'age' is the name 
  // 'age' is capable of holding integer values
  // positive/negative whole numbers or 0
  // '=' is the assignment operator
  // '28' is the value
}

ただし、これはPythonで上記を記述する方法です。

age = 28

#'age' is the variable name, or identifier
# '=' is the assignment operator
#'28' is the value assigned to the variable, so '28' is the value of 'age'

変数名は常に左側にあり、代入する値は代入演算子の後に右側に配置されます。

プログラムの存続期間中、変数の値を変更できることに注意してください。

my_age = 28

print(f"My age in 2022 is {my_age}.")

my_age = 29

print(f"My age in 2023 will be {my_age}.")

#output

#My age in 2022 is 28.
#My age in 2023 will be 29.

同じ変数名を保持しますが、値をからにmy_age変更するだけです。2829

Pythonの可変スコープとはどういう意味ですか?

変数スコープとは、変数が利用可能で、アクセス可能で、表示可能なPythonプログラムの部分と境界を指します。

Python変数のスコープには4つのタイプがあり、 LEGBルールとも呼ばれます。

  • 局所
  • 囲み
  • グローバル
  • ビルトイン

この記事の残りの部分では、グローバルスコープを使用した変数の作成について学習することに焦点を当て、ローカル変数スコープとグローバル変数スコープの違いを理解します。

Pythonでローカルスコープを使用して変数を作成する方法

関数の本体内で定義された変数にはローカルスコープがあります。つまり、その特定の関数内でのみアクセスできます。言い換えれば、それらはその関数に対して「ローカル」です。

ローカル変数にアクセスするには、関数を呼び出す必要があります。

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()


#output

#The best place to learn to code is with freeCodeCamp!

関数の本体の外部からローカルスコープを使用してその変数にアクセスしようとするとどうなるかを見てください。

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#try to print local variable 'coding_website' from outside the function
print(coding_website)

#output

#NameError: name 'coding_website' is not defined

NameErrorプログラムの残りの部分では「表示」されないため、aが発生します。定義された関数内でのみ「表示」されます。

Pythonでグローバルスコープを使用して変数を作成する方法

ファイルの先頭など、関数の外部で変数を定義すると、その変数はグローバルスコープを持ち、グローバル変数と呼ばれます。

グローバル変数は、プログラムのどこからでもアクセスできます。

関数の本体内で使用することも、関数の外部からアクセスすることもできます。

#create a global variable
coding_website = "freeCodeCamp"

def learn_to_code():
    #access the variable 'coding_website' inside the function
    print(f"The best place to learn to code is with {coding_website}!")

#call the function
learn_to_code()

#access the variable 'coding_website' from outside the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

グローバル変数とローカル変数があり、両方が同じ名前の場合はどうなりますか?

#global variable
city = "Athens"

def travel_plans():
    #local variable with the same name as the global variable
    city = "London"
    print(f"I want to visit {city} next year!")

#call function - this will output the value of local variable
travel_plans()

#reference global variable - this will output the value of global variable
print(f"I want to visit {city} next year!")

#output

#I want to visit London next year!
#I want to visit Athens next year!

上記の例では、その特定の出力を期待していなかった可能性があります。

city関数内で別の値を割り当てたときに、の値が変わると思ったかもしれません。

たぶん、私が行でグローバル変数を参照したときprint(f" I want to visit {city} next year!")、出力は#I want to visit London next year!の代わりになると予想しました#I want to visit Athens next year!

ただし、関数が呼び出されると、ローカル変数の値が出力されます。

次に、関数の外部でグローバル変数を参照すると、グローバル変数に割り当てられた値が出力されました。

彼らはお互いに干渉しませんでした。

ただし、グローバル変数とローカル変数に同じ変数名を使用することは、ベストプラクティスとは見なされません。プログラムを実行すると混乱する結果が生じる可能性があるため、変数の名前が同じでないことを確認してください。

Pythonでキーワードを使用する方法global

グローバル変数があり、関数内でその値を変更したい場合はどうなりますか?

私がそれをしようとすると何が起こるか見てください:

#global variable
city = "Athens"

def travel_plans():
    #First, this is like when I tried to access the global variable defined outside the function. 
    # This works fine on its own, as you saw earlier on.
    print(f"I want to visit {city} next year!")

    #However, when I then try to re-assign a different value to the global variable 'city' from inside the function,
    #after trying to print it,
    #it will throw an error
    city = "London"
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#output

#UnboundLocalError: local variable 'city' referenced before assignment

デフォルトでは、Pythonは関数内でローカル変数を使用したいと考えています。

そのため、最初に変数の値を出力してから、アクセスしようとしている変数に値再割り当てしようとすると、Pythonが混乱します。

関数内のグローバル変数の値を変更する方法は、次のglobalキーワードを使用することです。

#global variable
city = "Athens"

#print value of global variable
print(f"I want to visit {city} next year!")

def travel_plans():
    global city
    #print initial value of global variable
    print(f"I want to visit {city} next year!")
    #assign a different value to global variable from within function
    city = "London"
    #print new value
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#print value of global variable
print(f"I want to visit {city} next year!")

global次のエラーが発生するため、関数でキーワードを参照する前にキーワードを使用してくださいSyntaxError: name 'city' is used prior to global declaration

以前、関数内で作成された変数はローカルスコープを持っているため、それらにアクセスできないことを確認しました。

globalキーワードは、関数内で宣言された変数の可視性を変更します。

def learn_to_code():
   global coding_website
   coding_website = "freeCodeCamp"
   print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()

#access variable from within the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

結論

そして、あなたはそれを持っています!これで、Pythonのグローバル変数の基本を理解し、ローカル変数とグローバル変数の違いを理解できます。

この記事がお役に立てば幸いです。

基本から始めて、インタラクティブで初心者に優しい方法で学びます。また、最後に5つのプロジェクトを構築して実践し、学んだことを強化するのに役立てます。

読んでくれてありがとう、そして幸せなコーディング!

ソース:https ://www.freecodecamp.org/news/python-global-variables-examples/

#python 

Pythonグローバル変数–グローバル変数の例を定義する方法

Variables Globales De Python: Cómo Definir Un Ejemplo De Variable Glob

En este artículo, aprenderá los conceptos básicos de las variables globales.

Para empezar, aprenderá cómo declarar variables en Python y qué significa realmente el término 'ámbito de variable'.

Luego, aprenderá las diferencias entre variables locales y globales y comprenderá cómo definir variables globales y cómo usar la globalpalabra clave.

¿Qué son las variables en Python y cómo se crean? Una introducción para principiantes

Puede pensar en las variables como contenedores de almacenamiento .

Son contenedores de almacenamiento para almacenar datos, información y valores que le gustaría guardar en la memoria de la computadora. Luego puede hacer referencia a ellos o incluso manipularlos en algún momento a lo largo de la vida del programa.

Una variable tiene un nombre simbólico y puede pensar en ese nombre como la etiqueta en el contenedor de almacenamiento que actúa como su identificador.

El nombre de la variable será una referencia y un puntero a los datos almacenados en su interior. Por lo tanto, no es necesario recordar los detalles de sus datos e información; solo necesita hacer referencia al nombre de la variable que contiene esos datos e información.

Al dar un nombre a una variable, asegúrese de que sea descriptivo de los datos que contiene. Los nombres de las variables deben ser claros y fácilmente comprensibles tanto para usted en el futuro como para los otros desarrolladores con los que puede estar trabajando.

Ahora, veamos cómo crear una variable en Python.

Al declarar variables en Python, no necesita especificar su tipo de datos.

Por ejemplo, en el lenguaje de programación C, debe mencionar explícitamente el tipo de datos que contendrá la variable.

Entonces, si quisiera almacenar su edad, que es un número entero, o inttipo, esto es lo que tendría que hacer en C:

#include <stdio.h>
 
int main(void)
{
  int age = 28;
  // 'int' is the data type
  // 'age' is the name 
  // 'age' is capable of holding integer values
  // positive/negative whole numbers or 0
  // '=' is the assignment operator
  // '28' is the value
}

Sin embargo, así es como escribirías lo anterior en Python:

age = 28

#'age' is the variable name, or identifier
# '=' is the assignment operator
#'28' is the value assigned to the variable, so '28' is the value of 'age'

El nombre de la variable siempre está en el lado izquierdo y el valor que desea asignar va en el lado derecho después del operador de asignación.

Tenga en cuenta que puede cambiar los valores de las variables a lo largo de la vida de un programa:

my_age = 28

print(f"My age in 2022 is {my_age}.")

my_age = 29

print(f"My age in 2023 will be {my_age}.")

#output

#My age in 2022 is 28.
#My age in 2023 will be 29.

Mantienes el mismo nombre de variable my_age, pero solo cambias el valor de 28a 29.

¿Qué significa el alcance variable en Python?

El alcance de la variable se refiere a las partes y los límites de un programa de Python donde una variable está disponible, accesible y visible.

Hay cuatro tipos de alcance para las variables de Python, que también se conocen como la regla LEGB :

  • local ,
  • Encerrando ,
  • globales ,
  • Incorporado .

En el resto de este artículo, se centrará en aprender a crear variables con alcance global y comprenderá la diferencia entre los alcances de variables locales y globales.

Cómo crear variables con alcance local en Python

Las variables definidas dentro del cuerpo de una función tienen alcance local , lo que significa que solo se puede acceder a ellas dentro de esa función en particular. En otras palabras, son 'locales' para esa función.

Solo puede acceder a una variable local llamando a la función.

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()


#output

#The best place to learn to code is with freeCodeCamp!

Mire lo que sucede cuando trato de acceder a esa variable con un alcance local desde fuera del cuerpo de la función:

def learn_to_code():
    #create local variable
    coding_website = "freeCodeCamp"
    print(f"The best place to learn to code is with {coding_website}!")

#try to print local variable 'coding_website' from outside the function
print(coding_website)

#output

#NameError: name 'coding_website' is not defined

Plantea un NameErrorporque no es 'visible' en el resto del programa. Solo es 'visible' dentro de la función donde se definió.

Cómo crear variables con alcance global en Python

Cuando define una variable fuera de una función, como en la parte superior del archivo, tiene un alcance global y se conoce como variable global.

Se accede a una variable global desde cualquier parte del programa.

Puede usarlo dentro del cuerpo de una función, así como acceder desde fuera de una función:

#create a global variable
coding_website = "freeCodeCamp"

def learn_to_code():
    #access the variable 'coding_website' inside the function
    print(f"The best place to learn to code is with {coding_website}!")

#call the function
learn_to_code()

#access the variable 'coding_website' from outside the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

¿Qué sucede cuando hay una variable global y local, y ambas tienen el mismo nombre?

#global variable
city = "Athens"

def travel_plans():
    #local variable with the same name as the global variable
    city = "London"
    print(f"I want to visit {city} next year!")

#call function - this will output the value of local variable
travel_plans()

#reference global variable - this will output the value of global variable
print(f"I want to visit {city} next year!")

#output

#I want to visit London next year!
#I want to visit Athens next year!

En el ejemplo anterior, tal vez no esperaba ese resultado específico.

Tal vez pensaste que el valor de citycambiaría cuando le asignara un valor diferente dentro de la función.

Tal vez esperabas que cuando hice referencia a la variable global con la línea print(f" I want to visit {city} next year!"), la salida sería en #I want to visit London next year!lugar de #I want to visit Athens next year!.

Sin embargo, cuando se llamó a la función, imprimió el valor de la variable local.

Luego, cuando hice referencia a la variable global fuera de la función, se imprimió el valor asignado a la variable global.

No interfirieron entre sí.

Dicho esto, usar el mismo nombre de variable para variables globales y locales no se considera una buena práctica. Asegúrese de que sus variables no tengan el mismo nombre, ya que puede obtener algunos resultados confusos cuando ejecute su programa.

Cómo usar la globalpalabra clave en Python

¿Qué sucede si tiene una variable global pero desea cambiar su valor dentro de una función?

Mira lo que sucede cuando trato de hacer eso:

#global variable
city = "Athens"

def travel_plans():
    #First, this is like when I tried to access the global variable defined outside the function. 
    # This works fine on its own, as you saw earlier on.
    print(f"I want to visit {city} next year!")

    #However, when I then try to re-assign a different value to the global variable 'city' from inside the function,
    #after trying to print it,
    #it will throw an error
    city = "London"
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#output

#UnboundLocalError: local variable 'city' referenced before assignment

Por defecto, Python piensa que quieres usar una variable local dentro de una función.

Entonces, cuando intento imprimir el valor de la variable por primera vez y luego reasignar un valor a la variable a la que intento acceder, Python se confunde.

La forma de cambiar el valor de una variable global dentro de una función es usando la globalpalabra clave:

#global variable
city = "Athens"

#print value of global variable
print(f"I want to visit {city} next year!")

def travel_plans():
    global city
    #print initial value of global variable
    print(f"I want to visit {city} next year!")
    #assign a different value to global variable from within function
    city = "London"
    #print new value
    print(f"I want to visit {city} next year!")

#call function
travel_plans()

#print value of global variable
print(f"I want to visit {city} next year!")

Utilice la globalpalabra clave antes de hacer referencia a ella en la función, ya que obtendrá el siguiente error: SyntaxError: name 'city' is used prior to global declaration.

Anteriormente, vio que no podía acceder a las variables creadas dentro de las funciones ya que tienen un alcance local.

La globalpalabra clave cambia la visibilidad de las variables declaradas dentro de las funciones.

def learn_to_code():
   global coding_website
   coding_website = "freeCodeCamp"
   print(f"The best place to learn to code is with {coding_website}!")

#call function
learn_to_code()

#access variable from within the function
print(coding_website)

#output

#The best place to learn to code is with freeCodeCamp!
#freeCodeCamp

Conclusión

¡Y ahí lo tienes! Ahora conoce los conceptos básicos de las variables globales en Python y puede distinguir las diferencias entre las variables locales y globales.

Espero que hayas encontrado útil este artículo.

Comenzará desde lo básico y aprenderá de una manera interactiva y amigable para principiantes. También construirá cinco proyectos al final para poner en práctica y ayudar a reforzar lo que ha aprendido.

¡Gracias por leer y feliz codificación!

Fuente: https://www.freecodecamp.org/news/python-global-variables-examples/

#python 

Variables Globales De Python: Cómo Definir Un Ejemplo De Variable Glob

Cómo Usar Variables Globales Idiomáticamente En Rust

Declarar y usar variables globales en Rust puede ser complicado. Por lo general, para este lenguaje, Rust garantiza la solidez al obligarnos a ser muy explícitos.

En este artículo, discutiré las trampas de las que el compilador de Rust quiere salvarnos. Luego le mostraré las mejores soluciones disponibles para diferentes escenarios.

Visión de conjunto

Hay muchas opciones para implementar el estado global en Rust. Si tiene prisa, aquí hay una descripción general rápida de mis recomendaciones.

Un diagrama de flujo para encontrar la mejor solución para variables globales

Puede saltar a secciones específicas de este artículo a través de los siguientes enlaces:

Un primer intento ingenuo de usar variables globales en Rust

Comencemos con un ejemplo de cómo no usar variables globales. Supongamos que quiero almacenar la hora de inicio del programa en una cadena global. Más tarde, quiero acceder al valor de varios subprocesos.

Un principiante de Rust podría sentirse tentado a declarar una variable global exactamente como cualquier otra variable en Rust, usando let. El programa completo podría verse así:

use chrono::Utc;

let START_TIME = Utc::now().to_string();

pub fn main() {
    let thread_1 = std::thread::spawn(||{
        println!("Started {}, called thread 1 {}", START_TIME.as_ref().unwrap(), Utc::now());
    });
    let thread_2 = std::thread::spawn(||{
        println!("Started {}, called thread 2 {}", START_TIME.as_ref().unwrap(), Utc::now());
    });

    // Join threads and panic on error to show what went wrong
    thread_1.join().unwrap();
    thread_2.join().unwrap();
}

¡ Pruébelo usted mismo en el patio de recreo !

 

Esta es una sintaxis no válida para Rust. La letpalabra clave no se puede utilizar en el ámbito global. Solo podemos usar statico const. Este último declara una verdadera constante, no una variable. Solo staticnos da una variable global.

El razonamiento detrás de esto es que letasigna una variable en la pila, en tiempo de ejecución. Tenga en cuenta que esto sigue siendo cierto cuando se asigna en el montón, como en let t = Box::new();. En el código de máquina generado, todavía hay un puntero en el montón que se almacena en la pila.

Las variables globales se almacenan en el segmento de datos del programa. Tienen una dirección fija que no cambia durante la ejecución. Por lo tanto, el segmento de código puede incluir direcciones constantes y no requiere ningún espacio en la pila.

Bien, entonces podemos entender por qué necesitamos una sintaxis diferente. Rust, como lenguaje de programación de sistemas modernos, quiere ser muy explícito sobre la gestión de la memoria.

Probemos de nuevo con static:

use chrono::Utc;

static START_TIME: String = Utc::now().to_string();

pub fn main() {
    // ...
}

El compilador no está contento, todavía:

error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
 --> src/main.rs:3:24
  |
3 | static start: String = Utc::now().to_string();
  |                        ^^^^^^^^^^^^^^^^^^^^^^

Hm, por lo que el valor de inicialización de una variable estática no se puede calcular en tiempo de ejecución. Entonces, ¿tal vez dejar que no se inicialice?

use chrono::Utc;

static START_TIME;

pub fn main() {
    // ...
}

Esto produce un nuevo error:

Compiling playground v0.0.1 (/playground)
error: free static item without body
 --> src/main.rs:21:1
  |
3 | static START_TIME;
  | ^^^^^^^^^^^^^^^^^-
  |                  |
  |                  help: provide a definition for the static: `= <expr>;`

¡Entonces eso tampoco funciona! Todos los valores estáticos deben inicializarse por completo y ser válidos antes de que se ejecute cualquier código de usuario.

Si viene a Rust desde otro lenguaje, como JavaScript o Python, esto puede parecer innecesariamente restrictivo. Pero cualquier gurú de C ++ puede contarle historias sobre el fiasco del orden de inicialización estático , que puede conducir a un orden de inicialización indefinido si no tenemos cuidado.

Por ejemplo, imagina algo como esto:

static A: u32 = foo();
static B: u32 = foo();
static C: u32 = A + B;

fn foo() -> u32 {
    C + 1
}

fn main() {
    println!("A: {} B: {} C: {}", A, B, C);
}

En este fragmento de código, no hay un orden de inicialización seguro debido a las dependencias circulares.

Si fuera C++, al que no le importa la seguridad, el resultado sería A: 1 B: 1 C: 2. Se inicializa en cero antes de que se ejecute cualquier código y luego el orden se define de arriba a abajo dentro de cada unidad de compilación.

Al menos está definido cuál es el resultado. Sin embargo, el “fiasco” comienza cuando las variables estáticas son de .cpparchivos diferentes y, por lo tanto, unidades de compilación diferentes. Luego, el orden no está definido y generalmente depende del orden de los archivos en la línea de comando de compilación.

En Rust, la inicialización cero no es una cosa. Después de todo, cero es un valor no válido para muchos tipos, como Box. Además, en Rust, no aceptamos problemas de orden extraños. Mientras nos mantengamos alejados de unsafe, el compilador solo debería permitirnos escribir código sensato. Y es por eso que el compilador evita que usemos una inicialización de tiempo de ejecución directa.

Pero, ¿puedo eludir la inicialización usando None, el equivalente de un puntero nulo? Al menos todo esto está de acuerdo con el sistema de tipo Rust. Seguramente puedo mover la inicialización a la parte superior de la función principal, ¿verdad?

static mut START_TIME: Option<String> = None;

pub fn main() {
    START_TIME = Some(Utc::now().to_string());
    // ...
}

Ah, bueno, el error que obtenemos es...

error[E0133]: use of mutable static is unsafe and requires unsafe function or block
  --> src/main.rs:24:5
  |
6 |     START_TIME = Some(Utc::now().to_string());
  |     ^^^^^^^^^^ use of mutable static
  |
  = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior

En este punto, podría envolverlo en un unsafe{...}bloque y funcionaría. A veces, esta es una estrategia válida. Tal vez para probar si el resto del código funciona como se esperaba. Pero no es la solución idiomática lo que quiero mostrarte. Entonces, exploremos soluciones que el compilador garantiza que son seguras.

Refactorizar el ejemplo

Es posible que ya haya notado que este ejemplo no requiere variables globales en absoluto. Y la mayoría de las veces, si podemos pensar en una solución sin variables globales, debemos evitarlas.

La idea aquí es poner la declaración dentro de la función principal:

pub fn main() {
    let start_time = Utc::now().to_string();
    let thread_1 = std::thread::spawn(||{
        println!("Started {}, called thread 1 {}", &start_time, Utc::now());
    });
    let thread_2 = std::thread::spawn(||{
        println!("Started {}, called thread 2 {}", &start_time, Utc::now());
    });

    // Join threads and panic on error to show what went wrong
    thread_1.join().unwrap();
    thread_2.join().unwrap();
}

El único problema es el verificador de préstamos:

error[E0373]: closure may outlive the current function, but it borrows `start_time`, which is owned by the current function
  --> src/main.rs:42:39
   |
42 |     let thread_1 = std::thread::spawn(||{
   |                                       ^^ may outlive borrowed value `start_time`
43 |         println!("Started {}, called thread 1 {}", &start_time, Utc::now());
   |                                                     ---------- `start_time` is borrowed here
   |
note: function requires argument type to outlive `'static`

Este error no es exactamente obvio. El compilador nos dice que el subproceso generado puede durar más que el valor start_time, que vive en el marco de la pila de la función principal.

Técnicamente, podemos ver que esto es imposible. Los subprocesos se unen, por lo que el subproceso principal no se cerrará antes de que los subprocesos hayan terminado.

Pero el compilador no es lo suficientemente inteligente como para resolver este caso en particular. En general, cuando se genera un nuevo subproceso, el cierre proporcionado solo puede tomar prestados elementos con una vida útil estática. En otras palabras, los valores prestados deben estar vivos durante la vida útil completa del programa.

Para cualquiera que esté aprendiendo sobre Rust, este podría ser el punto en el que desea llegar a las variables globales. Pero hay al menos dos soluciones que son mucho más fáciles que eso. El más simple es clonar el valor de la cadena y luego mover la propiedad de las cadenas a los cierres. Por supuesto, eso requiere una asignación adicional y algo de memoria adicional. Pero en este caso, es solo una cadena corta y nada crítico para el rendimiento.

Pero, ¿y si fuera un objeto mucho más grande para compartir? Si no desea clonarlo, envuélvalo detrás de un puntero inteligente contado por referencia. Rc es el tipo de conteo de referencia de subproceso único. Arc es la versión atómica que puede compartir valores de forma segura entre subprocesos.

Entonces, para satisfacer al compilador, podemos usar Arclo siguiente:

/* Final Solution */
pub fn main() {
    let start_time = Arc::new(Utc::now().to_string());
    // This clones the Arc pointer, not the String behind it
    let cloned_start_time = start_time.clone();
    let thread_1 = std::thread::spawn(move ||{
        println!("Started {}, called thread 1 {}", cloned_start_time, Utc::now());
    });
    let thread_2 = std::thread::spawn(move ||{
        println!("Started {}, called thread 2 {}", start_time, Utc::now());
    });

    // Join threads and panic on error to show what went wrong
    thread_1.join().unwrap();
    thread_2.join().unwrap();
}

¡ Pruébelo usted mismo en el patio de recreo !

 

Este ha sido un resumen rápido sobre cómo compartir el estado entre subprocesos y evitar las variables globales. Más allá de lo que le he mostrado hasta ahora, es posible que también necesite mutabilidad interior para modificar el estado compartido. La cobertura completa de la mutabilidad interior está fuera del alcance de este artículo. Pero en este ejemplo en particular, elegiría Arc<Mutex<String>>agregar mutabilidad interior segura para subprocesos a start_time.

Cuando el valor de la variable global se conoce en tiempo de compilación

En mi experiencia, los casos de uso más comunes para el estado global no son variables sino constantes. En Rust, vienen en dos sabores:

  • Valores constantes, definidos con const. Estos están en línea por el compilador. Nunca se permite la mutabilidad interior.
  • Variables estáticas, definidas con static. Reciben un espacio fijo en el segmento de datos. La mutabilidad interior es posible.

Ambos se pueden inicializar con constantes de tiempo de compilación . Estos pueden ser valores simples, como 42o "hello world". O podría ser una expresión que involucre varias otras constantes y funciones de tiempo de compilación marcadas como const. Siempre y cuando evitemos las dependencias circulares. (Puede encontrar más detalles sobre las expresiones constantes en The Rust Reference ).

use std::sync::atomic::AtomicU64;
use std::sync::{Arc,Mutex};

static COUNTER: AtomicU64 = AtomicU64::new(TI_BYTE);

const GI_BYTE: u64 = 1024 * 1024 * 1024;
const TI_BYTE: u64 = 1024 * GI_BYTE;

Por lo general, constes la mejor opción, a menos que necesite mutabilidad interior o que desee evitar específicamente la incorporación.

Si necesita mutabilidad interior, hay varias opciones. Para la mayoría de las primitivas, hay una variante atómica correspondiente disponible en std::sync::atomic . Proporcionan una API limpia para cargar, almacenar y actualizar valores de forma atómica.

En ausencia de elementos atómicos, la elección habitual es un candado. La biblioteca estándar de Rust ofrece un bloqueo de lectura y escritura ( RwLock) y un bloqueo de exclusión mutua ( Mutex).

Sin embargo, si necesita calcular el valor en tiempo de ejecución, o necesita una asignación de montón, entonces consty staticno son de ayuda.

Variables globales de subproceso único en Rust con inicialización en tiempo de ejecución

La mayoría de las aplicaciones que escribo solo tienen un único hilo. En ese caso, no es necesario un mecanismo de bloqueo.

Sin embargo, no deberíamos usar static mutdirectamente y envolver los accesos en unsafe, solo porque solo hay un hilo. De esta manera, podríamos terminar con una grave corrupción de la memoria.

Por ejemplo, tomar prestado de forma insegura de la variable global podría darnos múltiples referencias mutables simultáneamente. Entonces podríamos usar uno de ellos para iterar sobre un vector y otro para eliminar valores del mismo vector. Entonces, el iterador podría ir más allá del límite de la memoria válida, un bloqueo potencial que Rust seguro habría evitado.

Pero la biblioteca estándar tiene una forma de almacenar valores "globalmente" para un acceso seguro dentro de un solo hilo. Estoy hablando de hilos locales . En presencia de muchos hilos, cada hilo obtiene una copia independiente de la variable. Pero en nuestro caso, con un solo hilo, solo hay una copia.

Los hilos locales se crean con la thread_local!macro. Acceder a ellos requiere el uso de un cierre, como se muestra en el siguiente ejemplo:

use chrono::Utc;

thread_local!(static GLOBAL_DATA: String = Utc::now().to_string());

fn main() {
    GLOBAL_DATA.with(|text| {
        println!("{}", *text);
    });
}

No es la más simple de todas las soluciones. Pero nos permite realizar un código de inicialización arbitrario, que se ejecutará justo a tiempo cuando se produzca el primer acceso al valor.

Los hilos locales son realmente buenos cuando se trata de mutabilidad interior. A diferencia de todas las demás soluciones, no requiere Sync . Esto permite usar RefCell para la mutabilidad interior, lo que evita la sobrecarga de bloqueo de Mutex .

El rendimiento absoluto de los subprocesos locales depende en gran medida de la plataforma. Pero hice algunas pruebas rápidas en mi propia PC comparándola con la mutabilidad interior basada en bloqueos y descubrí que es 10 veces más rápida. No espero que el resultado cambie en ninguna plataforma, pero asegúrese de ejecutar sus propios puntos de referencia si le importa mucho el rendimiento.

Aquí hay un ejemplo de cómo usar RefCellpara la mutabilidad interior:

thread_local!(static GLOBAL_DATA: RefCell<String> = RefCell::new(Utc::now().to_string()));

fn main() {
    GLOBAL_DATA.with(|text| {
        println!("Global string is {}", *text.borrow());
    });

    GLOBAL_DATA.with(|text| {
        *text.borrow_mut() = Utc::now().to_string();
    });

    GLOBAL_DATA.with(|text| {
        println!("Global string is {}", *text.borrow());
    });
}

¡ Pruébelo usted mismo en el patio de recreo !

 

Como nota al margen, aunque los subprocesos en WebAssembly son diferentes de los subprocesos en una plataforma x86_64, este patrón con thread_local!+ RefCelltambién se aplica al compilar Rust para ejecutarlo en el navegador. Usar un enfoque que sea seguro para el código de subprocesos múltiples sería excesivo en ese caso. (Si la idea de ejecutar Rust dentro del navegador es nueva para usted, no dude en leer un artículo anterior que escribí llamado " Tutorial de Rust: una introducción a Rust para desarrolladores de JavaScript ".)

Una advertencia sobre los subprocesos locales es que su implementación depende de la plataforma. Por lo general, esto no es nada que notaría, pero tenga en cuenta que la semántica de caída depende de la plataforma debido a eso.

Dicho todo esto, las soluciones para globales de subprocesos múltiples obviamente también funcionan para los casos de un solo subproceso. Y sin la mutabilidad interior, parecen ser tan rápidos como los hilos locales.

Así que echemos un vistazo a eso a continuación.

Variables globales de subprocesos múltiples con inicialización en tiempo de ejecución

La biblioteca estándar actualmente no tiene una gran solución para variables globales seguras con inicialización en tiempo de ejecución. Sin embargo, usando std::sync::Once , es posible construir algo que se use unsafede forma segura, si sabes lo que estás haciendo.

El ejemplo en la documentación oficial es un buen punto de partida. Si también necesita mutabilidad interior, tendría que combinar ese enfoque con un bloqueo de lectura y escritura o un mutex. Así es como podría verse:

static mut STD_ONCE_COUNTER: Option<Mutex<String>> = None;
static INIT: Once = Once::new();

fn global_string<'a>() -> &'a Mutex<String> {
    INIT.call_once(|| {
        // Since this access is inside a call_once, before any other accesses, it is safe
        unsafe {
            *STD_ONCE_COUNTER.borrow_mut() = Some(Mutex::new(Utc::now().to_string()));
        }
    });
    // As long as this function is the only place with access to the static variable,
    // giving out a read-only borrow here is safe because it is guaranteed no more mutable
    // references will exist at this point or in the future.
    unsafe { STD_ONCE_COUNTER.as_ref().unwrap() }
}
pub fn main() {
    println!("Global string is {}", *global_string().lock().unwrap());
    *global_string().lock().unwrap() = Utc::now().to_string();
    println!("Global string is {}", *global_string().lock().unwrap());
}

¡ Pruébelo usted mismo en el patio de recreo !

 

Si está buscando algo más simple, le recomiendo una de las dos cajas, de las que hablaré en la siguiente sección.

Bibliotecas externas para administrar variables globales en Rust

Basándome en la popularidad y el gusto personal, quiero recomendar dos bibliotecas que creo que son la mejor opción para variables globales sencillas en Rust, a partir de 2021.

Once Cell se considera actualmente para la biblioteca estándar. (Consulte este problema de seguimiento ). Si está en un compilador nocturno, ya puede usar la API inestable para agregarlo #![feature(once_cell)]a su proyecto main.rs.

Aquí hay un ejemplo que se usa once_cellen un compilador estable, con la dependencia adicional:

use once_cell::sync::Lazy;

static GLOBAL_DATA: Lazy<String> = Lazy::new(||Utc::now().to_string());

fn main() {
    println!("{}", *GLOBAL_DATA);
}

¡ Pruébelo usted mismo en el patio de recreo !

 

Finalmente, también está Lazy Static , actualmente la caja más popular para la inicialización de variables globales. Utiliza una macro con una pequeña extensión de sintaxis ( static ref) para definir variables globales.

Aquí está el mismo ejemplo de nuevo, traducido de once_cella lazy_static:

#[macro_use]
extern crate lazy_static;

lazy_static!(
    static ref GLOBAL_DATA: String = Utc::now().to_string();
);

fn main() {
    println!("{}", *GLOBAL_DATA);
}

¡ Pruébelo usted mismo en el patio de recreo !

 

La decisión entre once_celly lazy_staticesencialmente se reduce a qué sintaxis te gusta más.
Además, ambos admiten la mutabilidad interior. Simplemente envuelva el Stringen a Mutexo RwLock.

Conclusión

Estas han sido todas las formas (sensatas) de implementar variables globales en Rust que conozco. Ojalá fuera más sencillo. Pero el estado global es inherentemente complejo. En combinación con las garantías de seguridad de la memoria de Rust, una solución sencilla que los atrape parece imposible. Pero espero que este artículo te haya ayudado a ver a través de la gran cantidad de opciones disponibles.

En general, la comunidad de Rust tiende a otorgar el máximo poder al usuario, lo que complica las cosas como efecto secundario.

Puede ser difícil hacer un seguimiento de todos los detalles. Como resultado, paso mucho de mi tiempo libre jugando con las características de Rust para explorar las posibilidades. En el proceso, generalmente implemento proyectos de pasatiempos más pequeños o más grandes, como videojuegos, y los subo a mi perfil de GitHub. Luego, si encuentro algo interesante en mi experimentación con el idioma, lo escribo en mi blog privado. Compruébelo si desea leer más contenido de Rust en profundidad  

Fuente: https://www.sitepoint.com/rust-global-variables/ 

#rust #global 

Cómo Usar Variables Globales Idiomáticamente En Rust
Vishal shah

Vishal shah

1641384157

"5 Years and 5 Milestones achieved"

Congratulations to all the employees, clients, partners & Vendors on this very big occasion. It has been a wonderful journey altogether. Let’s hope for the best in the coming years!
 
It’s hard to believe NOW, was started 5 years ago. We started with a few but now we are many, not only in numbers but also in talents and creativity.
 
Xceltec has been to a whole new height with all the successes in all these years. Let’s make this day a big one for each one of us!
 
Xceltec so far has expertise in various domains, we have multiple ventures in different segments and a global presence in more than 5 countries.
 
IT Services, IT Consulting, Web & App Development, Ready Product Solution & Customization, Zimbra Email Hosting & Migration, IT Training cum Incubation with Overseas Consulting, E-healthcare & Telemedicine Solution are few of the domains and segments Xceltec is expert in.
 
It’s not just a corporate anniversary, it’s an anniversary of a family that only grew strong defying the odds. Happy (5th) anniversary!
 
#5yearanniversary #successjourney #xceltec #5years #journey #itcompany #growthjourney #happinesss #momentsthatmatter #webdevelopmentcompany #consulting #usa #global #globalbusinessservices

"5 Years and 5 Milestones achieved"

Optimizing Your Divi Site’s Logo Image with Global Presets

Optimizing your site’s logo in Divi is an important part of the design of your website. But, it doesn’t have to be a mysterious or daunting endeavor. In fact, Divi makes it pretty simple with the Divi Theme Builder and all of the built-in design options available.

In this tutorial, we are going to show you how to optimize your logos with the right size, position, and style in Divi. Then we’ll show you how to save those designs as global presets you can use for future development.

#global #divi #logo

Optimizing Your Divi Site’s Logo Image with Global Presets

Global IT Services | IT Outsourcing Company | Infognana

If you are planning to save your time and money, outsourcing would be the best option you could choose. Experts at Infognana helps you out throughout the process and scale up your business. Get flexible IT outsourcing services globally. With experts across multiple verticals, Infognana would be your perfect tech partner!

#outsourcing #services #global #it #outsourcing

Arvel  Miller

Arvel Miller

1603439853

The Nuances of Constants in Go; Go Isn't JavaScript

Constants can be confusing and easy to misuse in Go if you are coming from an untyped language. Let’s take a look at some of the nuanced details of how they work in Go. It’s probably unsurprising, but Go’s constants are almost nothing like JavaScript’s bastardized version of the concept.

Go vs JavaScript

Many programming languages support constants, often denoted by the keyword const.

Go and JavaScript both declare new constants in the same way:

const frameRate = 60

Constants in Go

  • Must be able to be assigned at compile time. The value of a const can’t be the result of a runtime calculation.
  • Run faster because the compiler can make specific optimizations.
  • Cannot change. The compiler will not allow them to be re-assigned.
  • Only work with some types. Arrays, Slices, Maps, Structs, etc… can’t be made constant
  • Are not normal Go types unless explicitly assigned as such

#languages #clean code #engineering practices #golang #javascript #compile #const #constant #global #go #golang #javascript

The Nuances of Constants in Go; Go Isn't JavaScript
Ron  Cartwright

Ron Cartwright

1603069200

Silent Librarian Goes Back to School with Global Research-Stealing Effort

The Silent Librarian campaign has re-emerged for the fall school session, actively targeting students and faculty at universities via spear-phishing campaigns.

The threat group (also known as TA407 and Cobalt Dickens), which operates out of Iran, has been on the prowl since the start of the 2019 school year, launching low-volume, highly-targeted, socially engineered emails that eventually trick victims into handing over their login credentials. The goal is to harvest not just logins to sell online, but also proprietary university research and data, researchers said.

The emails typically masquerade as messages from university library systems or other on-campus divisions. Over the course of the last school year, the cyberattackers honed their efforts, and began using shortened URL links in their phishing emails, which make it more difficult to detect that victims are being redirected to an attacker-hosted landing page. The attackers also revamped their landing pages with new university-specific banners, based on weather alerts or emergency notifications, to make them look more authentic.

Now, this APT group is going back to school with a fresh campaign that seems to be targeting institutions globally, according to an analysis Tuesday from Malwarebytes. Targets stretch across a dozen countries and so far have included: The University of Adelaide in Australia; Glasgow Caledonian, University of Kent, University of York, King’s College London, Cambridge and others in the U.K.; the University of Toronto and McGill in Canada; and Stony Brook University, University of North Texas and others in the U.S.

The modus operandi seen last year remains in place, with Silent Librarian hosting a series of phishing sites that are built to mimic legitimate university domains. For instance, emails purporting to be from the University of Adelaide Library directed victims to a “library.adelaide.crev[dot]me” URL, which is very close to the legitimate “library.adelaide.edu.au” domain of the school.

“Many of these have been identified and taken down, [but] the threat actor has built enough of them to continue with a successful campaign against staff and students alike,” according to the analysis. “Clearly we only uncovered a small portion of this phishing operation. Although for the most part the sites are taken down quickly, the attacker has the advantage of being one step ahead and is going for many possible targets at once.”

#breach #hacks #web security #colleges #credential theft #credentials #global #irán #iranian hackers #library portals #malwarebytes #phishing #research #sanctions #silent librarian #stealing #universities

Silent Librarian Goes Back to School with Global Research-Stealing Effort